【问题标题】:EF: Inserting already present record in many to many relationshipEF:在多对多关系中插入已经存在的记录
【发布时间】:2018-06-11 08:07:40
【问题描述】:

对于我搜索的内容,有两种方法可以将已经存在的记录插入到 ICollection 列表中:

  1. group.Users.Add(db.Users.FirstOrDefault(x=> x.Id = 1));
  2. var to_add = new User{Id: 1}; db.Users.Attach(to_add); group.Users.Add(to_add);

上述两种方法的问题是每次我们想要添加记录时都会调用数据库。虽然我们已经知道用户的 ID 和组的 ID,但这就是创建关系所需的全部内容。

想象一下要添加一个长列表,以上两种方法都会多次调用 db。

【问题讨论】:

  • 选项 1 => 因为db.Users.FirstOrDefault(x=> x.Id = 1) 选项 2 => 没有调用数据库,所以只调用了一次数据库。旁注:那里不需要附加。
  • @CodeNotFound 注意,用户模型不仅包括Id 列,还包括NameDescription 等。如果我不添加它们,EF 不会给出有效性错误?
  • 了解正在发生的事情的最佳方式是拥有一个代表您在实际项目中真正拥有的示例代码。您还可以分析和验证您所说的内容。
  • 是的,因为名称是必需的,在group.Users.Add(to_add) 上没有attach ef 给出验证错误。
  • Add 实现已经调用 Attach 所以你的错误可能是别的东西。

标签: sql sql-server entity-framework linq


【解决方案1】:

所以你有GroupsUsers。每个Group 有零个或多个Users;每个User 都有零个或多个Groups。传统的多对多关系。

通常人们会将User 添加到Group,或将Group 添加到User。但是您没有Group,也没有User,您只有GroupIdUserId。并且由于大量插入,您不想获取要创建关系的UsersGroups

问题是,如果您可以将 GroupId-UserId 组合直接添加到您的联结表中,您怎么知道您不会添加已经存在的 Group-User 关系?如果你不在乎,你最终会得到两倍的关系。这会导致问题:如果您询问UsersGroup,您是否希望它们显示两次?如果关系结束,应该删除哪一个,还是应该全部删除?

如果你真的想实现双重关系的可能性,那么你需要Implement a a Custom Junction Table as described here额外的字段将是关系的数量。

这对您的大批量没有帮助,因为您仍需要从自定义联结表中获取字段以增加 NrOfRelations 值。

另一方面,如果您不想要双重关系,则必须检查该值是否已经存在,并且您不想在插入之前获取数据。

通常,添加到数据库的次数远少于查询次数。如果你有大量的数据要插入,那么通常只是在数据库的初始化阶段。我不会费心优化初始化太多。

考虑在字典中记住已经提取的组和用户,防止它们被提取两次。但是,如果您的列表非常庞大,这不是一个实用的解决方案。

如果您确实需要长时间使用此功能,请考虑创建一个存储过程来检查联结表中是否已经存在 GroupId / UserId,如果不存在,请添加它。

【讨论】:

  • 好的,感谢联结表上的主键确保没有重复。但是,我坚信应该有比从数据库中获取记录只是为了在联结表中插入主键更好的选择。
猜你喜欢
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-23
  • 1970-01-01
  • 1970-01-01
  • 2014-09-16
  • 2021-01-23
相关资源
最近更新 更多