【问题标题】:EF: many-to-many why Clear() does not generate only one sql call?EF:多对多为什么 Clear() 不只生成一个 sql 调用?
【发布时间】:2013-08-26 21:01:43
【问题描述】:

拥有 2 个实体:A *<-->* B多对多关系和对应的 3 个表:A, B, AB

尝试以下代码:

 var tempA = this.dbContext.A.
                  .Where(a => a.UID == 1)
                  .FirstOrDefault();

 // {check for null here}

 tempA.B.Clear();

 this.dbContext.SaveChanges();

似乎在tempA.B 集合中为每个b 生成对数据库的多个“删除” sql 调用(有点奇怪,除非我错过了什么)。

所以,如果我的 AB 表有这 2 条记录 = { (1,2) , (1,3) } ,上面的代码会产生两个“删除”sql 调用(一个用于 b=2,另一个用于 b= 3),像这样:

 1. DELETE FROM AB WHERE (A_UID = 1) AND (B_UID = 2)
 and 
 2. DELETE FROM AB WHERE (A_UID = 1) AND (B_UID = 3) 

但我想要一些 EF 代码,它可以产生如下简单的东西?

 DELETE FROM AB WHERE (A_UID = 1) 

编辑:我不明白为什么 EF 解析所有内部引用并为它们中的每一个生成一个删除,而不是为所有它们生成一个删除。

【问题讨论】:

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


【解决方案1】:
dbContext.Database.ExecuteSqlCommand("DELETE FROM AB WHERE (A_UID = 1)");

是使用单个 SQL 命令实现此目的的唯一方法。如果您已加载/附加全部或仅部分相关实体,EF 不会跟踪。在这种情况下,您可以致电Clear...

var tempA = new A { UID = 1, B = new List<B>() }
tempA.B.Add(new B { UID = 2 });

using (var dbContext = new MyContext())
{
    dbContext.A.Attach(tempA);
    tempA.B.Clear();
    dbContext.SaveChanges();
}

...在这种情况下,从 A.UID = 1 的连接表中删除所有条目将是错误的,因为通过清除集合,您只删除了 B.UID = 2 的实体,但没有删除 B.UID = 3 的实体。

【讨论】:

  • 好的,我想我现在明白 Clear() 只影响 EF 无法预测它们是否全部的附加实体......太糟糕了,没有其他简单的方法可以实现我想要的...我可能会去调用存储过程。
  • 我注意到命令或存储过程的执行是在一个单独的事务中完成的,而不是调用 SaveContext 的事务。对此有什么想法吗?谢谢!
  • @Cristi:如果您需要在单个事务中将它们包装到 TransactionScope 中,如下所示:stackoverflow.com/a/7525625/270591
  • 非常感谢您的帮助。是的,但现在我想它会进入关于 DTC 的第二部分。你能看看我的这个问题吗:stackoverflow.com/questions/18489291/…
  • @Cristi:抱歉,我不知道你的新问题的答案。
【解决方案2】:

为什么不这样做:

var temp = this.dbContext.AB.Where(ab => ab.A.UID == 1 && ab.B.UID == 2);
temp.Clear();

我没有测试它,但也许这会提供更好的想法?

【讨论】:

  • AB不是实体,只有A&B是实体,AB只是用于多对多关系的表
  • 为什么不创建 AB 实体?
  • 当使用数据库优先的方法时,EF 自动创建了模型...模型很好
猜你喜欢
  • 2022-01-13
  • 2016-07-13
  • 1970-01-01
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多