具有实体框架的多对多插入

时间:2011-04-09 19:56:56

标签: entity-framework linq-to-entities many-to-many

假设我有两个实体,每个实体有大约20个属性,并且像是这样的多对多关系:

User (Id int,Name string, .......)
Issue (Id int,Name string, .......)
IssueAssignment (UserId,RoleId)

我想创建一个新问题并将其分配给许多现有用户。如果我有这样的代码:

foreach(var userId in existingUserIds)
{
   int id = userId
   var user = _db.Users.First(r => r.Id == id);        
   issue.AssignedUsers.add(user);     
}

_db.Users.AddObject(user);
_db.SaveChanges();

我注意到,当我针对我的SQL数据库运行它时,效率似乎非常低效。如果我看看 SQL Profiler正在执行以下操作:

  1. SELECT TOP(1)* FROM User WHERE UserId = userId
  2. SELECT * FROM IssueAssignment ON User.Id = userId
  3. INSERT INTO User ....
  4. INSERT INTO IssueAssignment
  5. 我的问题是:
    (a)为什么(1)和(2)必须发生? (b)(1)和(2)都将我需要做的所有字段带回来进行对象投影来限制 田野,似乎也是不必要的工作。

    感谢您的帮助

1 个答案:

答案 0 :(得分:4)

我有一些可能的线索:

  1. 这就是EF的行为方式。 _db.Users实际上是一个查询,在查询上调用First意味着在数据库中执行查询。
  2. 我猜你正在使用带有T4模板的EFv4并且启用了延迟加载。 T4模板创建“聪明”的对象,这些对象能够修复其导航属性,因此一旦您向User添加Issue,它就会在内部触发修正并尝试将Issue添加到User 1}}。这反过来会触发与用户相关的所有问题的延迟加载。
  3. 所以诀窍是使用虚拟对象而不是真实用户。你知道id,你只想在新问题和现有用户之间创建实现。试试这个(适用于EFv4 +和POCO):

    foreach(var userId in existingUserIds)
    {
       var user = new User { Id = userId };
       var _db.Users.Attach(user); // User with this Id mustn't be already loaded       
       issue.AssignedUsers.Add(user);     
    }
    
    context.Issues.AddObject(issue);
    context.SaveChanges();