使用Entity Framework和SQL Server进行多对多插入

时间:2015-03-19 22:16:00

标签: c# sql-server entity-framework many-to-many entity-framework-6

在我们的数据库中,我们有这种父 - 子 - 孙关系是多对多关系(两次)。这通过两个交叉/交叉引用表发生。 Parent / Child / Grandschild表具有唯一的varchar功能键。以下是仅显示层次结构中第一步的简化版本:

Parent              Junction             Child
+----+-------+      +------+------+      +----+-------+
| PK | F_KEY |      | PK_1 | PK_2 |      | PK | F_KEY |
+----+-------+      +------+------+      +----+-------+
|  1 | AAA   |      |    1 |    1 |      |  1 | BBB   |
+----+-------+      +------+------+      +----+-------+

父母/子女/孙子女的记录数量都是数百万。

场合

我们需要处理我们已经给出父子孙子集合的情况,其中一些可能已经存在于数据库中。我们需要插入尚未存在的那些,忽略rest(基于功能键)。

所以当前的实施:

  1. 关闭autodetectChanges并禁用datacontext上的所有约束。
  2. 检查已存在的父母(使用F_KEY) - 插入不存在的父母
  3. 检查已存在的子项(F_KEY) - 插入不存在的子项,我认为手动更新EF
  4. 孙子们的同意
  5. 毫不奇怪 - 出现了问题,现在我们在联结表中缺少链接,我们不得不通过脚本修复此问题。

    这种实施并不适合我。开发者的争论是表现。原始实施没有执行:

    1. 给出父母名单 - 忽略现有名单
    2. 查看剩余的孩子 - 用DbEntries替换现有的孩子
    3. 对孙子们的同意
    4. 的SaveChanges()
    5. 没有表演。我的同事说 - 想一想:你必须进入父母,然后找回身份证。保存孩子,检索身份证,将这些用于第一个联络表等。'

      问题

      我该如何表演?我的意思是 - 它有效,但不是很容易维护,真的让我误解了。

      我有一个想法 - 如果我们使联结表包含如此唯一的功能键:

      Parent              Junction             Child
      +----+-------+      +------+------+      +----+-------+
      | PK | F_KEY |      | PK_1 | PK_2 |      | PK | F_KEY |
      +----+-------+      +------+------+      +----+-------+
      |  1 | AAA   |      |  AAA |  BBB |      |  1 | BBB   |
      +----+-------+      +------+------+      +----+-------+
      

      然后我们不必检索插入项目的ID以将它们存储在联结表中。那有意义吗? EF能够从中受益吗?

      如果这不起作用 - 我们不会以最佳状态使用EF - 我们不妨考虑使用存储过程或直接查询数据库。您可以完全节省EF的开销,至少可以完全控制我们正在做的事情,而EF不会在幕后为我们提供查询。

      对此有何看法?当然,任何其他建议都非常受欢迎。

1 个答案:

答案 0 :(得分:1)

对于这种任务,我会创建一个存储过程,接受几个表值参数https://msdn.microsoft.com/en-us/library/bb510489.aspx https://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx,其中包含新ParentsChildren,{{ 1}},JunctionsGrandChildren并在一个事务内执行服务器上的所有合并,而不将任何内容发送回客户端。

在类似的情况下,批量处理行的一堆MERGE T-SQL语句对我来说效果很好。

合并Junctions,然后合并Parents,然后合并Children个表格。然后在GrandChildrenJunction之间Parents。然后在ChildrenJunction之间Children

只要您需要合并的集合大小合理(例如,大约10K行),只需调用一次存储过程就能很好地工作。如果必须合并更多行,请考虑将它们分成较小的批次并多次调用存储过程。