标识列上具有父/子关系的SqlBulkCopy和DataTables

.net c# sqlbulkcopy sql-server

我们需要根据父表中的Identity主键更新多个具有父/子关系的表,父表由一个或多个子表作为外键引用。

  • 由于数据量很大,我们希望在内存中构建这些表,然后使用C#中的SqlBulkCopy从DataSet或单个DataTables更新数据库。
  • 我们还希望从多个线程,进程和可能的客户端并行执行此操作。

我们在F#中的原型显示了很多承诺,性能提高了34倍,但是这段代码强制了父表中已知的Identity值。如果没有强制,当SqlBulkCopy插入行时,Identity列会在数据库中正确生成,但Identity值不会在内存中的DataTable中更新。此外,即使它们是,也不清楚DataSet是否能正确地修复父/子关系,以便随后可以用正确的外键值写入子表。

任何人都可以解释如何使用SqlBulkCopy更新标识值,以及如何配置数据集以保留和更新父/子关系,如果在单个DataTables上调用DataAdapter到FillSchema时不自动完成。

我不想要的答案:

  • 读取数据库以查找当前最高的Identity值,然后在创建每个父行时手动递增它。不适用于多个进程/客户端,据我所知,失败的事务可能会导致某些标识值被跳过,因此这种方法可能会破坏关系。
  • 一次一个地写出父行,并要求返回Identity值。通过使用SqlBulkCopy,这至少会破坏一些收益(是的,有多个子行比父类行多,但仍有很多父行)。

类似于以下未回答的问题:

热门答案

首先:SqlBulkCopy不可能做你想要的。顾名思义,它只是一条“单行道”。我尽可能快地将数据移动到sql server中。它是旧的批量复制命令的.Net版本,它将原始文本文件导入表中。因此,如果使用SqlBulkCopy,则无法获取标识值。

我做了很多批量数据处理,并且多次遇到过这个问题。解决方案取决于您的体系结构和数据分布。以下是一些想法:

  • 为每个线程创建一组目标表,在这些表中导入。最后加入这些表格。其中大多数可以通过一种非常通用的方式实现,您可以从名为TABLENAME的表中自动生成名为TABLENAME_THREAD_ID的表。

  • 将ID生成完全移出数据库。例如,实现生成ID的中央Web服务。在这种情况下,您不应该为每个调用生成一个ID,而是生成ID范围。否则,网络开销通常会变成瓶颈。

  • 尝试为您的数据生成ID。如果可能的话,你的问题就会消失。不要说快“是不可能的”。也许您可以使用可以在后处理步骤中清理的字符串ID?

还有一点评论:使用BulkCopy时,因子34的增加会增加。如果要快速插入数据,请确保正确配置数据库。



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因