0

I'm trying to get an upsert working on a collection of IDs (not the primary key - that's an identity int column) on a table using dapper. This doesn't need to be a dapper function, just including in case that helps.

I'm wondering if it's possible (either through straight SQL or using a dapper function) to run an upsert on a collection of IDs (specifically an IEnumerable of ints).

I really only need a simple example to get me started, so an example would be:


I have three objects of type Foo:

  1. { "ExternalID" : 1010101, "DescriptorString" : "I am a descriptive string", "OtherStuff" : "This is some other stuff" }
  2. { "ExternalID" : 1010122, "DescriptorString" : "I am a descriptive string123", "OtherStuff" : "This is some other stuff123" }
  3. { "ExternalID" : 1033333, "DescriptorString" : "I am a descriptive string555", "OtherStuff" : "This is some other stuff555" }

I have a table called Bar, with those same column names (where only 1033333 exists):

Table Foo
Column ID | ExternalID | DescriptorString | OtherStuff
Value [1]|[1033333] |["I am a descriptive string555"]|["This is some other stuff555"]


John Saunders
  • 160,644
  • 26
  • 247
  • 397
someguy0005
  • 125
  • 2
  • 12
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Jan 23 '15 at 03:06
  • Are you aware of the MERGE statement? – John Saunders Jan 23 '15 at 03:07
  • Yes, but I haven't found any examples that work on a collection of items. – someguy0005 Jan 23 '15 at 03:08
  • I've just done something similar by passing the collection as XML, then breaking the XML into an internal table using XQuery. I don't own the code so I can't post it, but look into the `nodes` and `value` functions in SQL Server's XQuery support. That will show you how to "shred" XML into a table you can work with in a query. – John Saunders Jan 23 '15 at 03:10
  • the other option is to dump it to a flat temp table if you have direct access to the DB server and you can save yourself the hassle of shredding the xml. Shredding xml is not terribly hard but if I can avoid it with minimal effort I will. The only options are to manually do it in code or get it to the server and merge. – RubberChickenLeader Jan 23 '15 at 03:46

1 Answers1

0

Well, since you said that this didn't need to be dapper-based ;-), I will say that the fastest and cleanest way to get this data upserted is to use Table-Valued Parameters (TVPs) which were introduced in SQL Server 2008. You need to create a User-Defined Table Type (one time) to define the structure, and then you can use it in either ad hoc queries or pass to a stored procedure. But this way you don't need to export to a file just to import, nor do you need to convert it to XML just to convert it back to a table.

Rather than copy/paste a large code block, I have noted three links below where I have posted the code to do this (all here on S.O.). The first two links are the full code (SQL and C#) to accomplish this (the 2nd link being the most analogous to what you are trying to do). Each is a slight variation on the theme (which shows the flexibility of using TVPs). The third is another variation but not the full code as it just shows the differences from one of the first two in order to fit that particular situation. But in all 3 cases, the data is streamed from the app into SQL Server. There is no creating of any additional collection or external file; you use what you currently have and only need to duplicate the values of a single row at a time to be sent over. And on the SQL Server side, it all comes through as a populated Table Variable. This is far more efficient than taking data you already have in memory, converting it to a file (takes time and disk space) or XML (takes cpu and memory) or a DataTable (for SqlBulkCopy; takes cpu and memory) or something else, only to rely on an external factor such as the filesystem (the files will need to be cleaned up, right?) or need to parse out of XML.

Now, there are some issues with the MERGE command (see Use Caution with SQL Server's MERGE Statement) that might be a reason to avoid using it. So, I have posted the "upsert" code that I have been using for years to an answer on DBA.StackExchange:

Community
  • 1
  • 1
Solomon Rutzky
  • 46,688
  • 9
  • 128
  • 171