2012-01-15 100 views
17

自从一年以来,我一直使用EF4(不是代码优先),所以我并不是真正的专家。 我在使用关于保存n更新的多对多关系方面存在疑问。实体框架更新多对多关系:虚拟与否

我在某处读取了stackoverflow(我找不到url)解决方案 - 更新现有的多对多关系 - 是不声明“虚拟”属性;但是,如果我这样做,引擎无法加载容易加载的数据。

你能说明一下理由吗?其他网络,你能帮我找到关于这个主题的一些很酷的文档吗?

THX

回答

56

您可以更新许多一对多的关系,这种方式(如这给用户3角色5为例):

using (var context = new MyObjectContext()) 
{ 
    var user = context.Users.Single(u => u.UserId == 3); 
    var role = context.Roles.Single(r => r.RoleId == 5); 

    user.Roles.Add(role); 

    context.SaveChanges(); 
} 

如果User.Roles集合声明为virtualuser.Roles.Add(role);行确实会触发延迟加载,这意味着全部用户的角色在添加新角色之前首先从数据库加载。

这实际上令人不安,因为您不需要加载整个Roles集合以向用户添加新角色。

但这并不意味着您必须删除virtual关键字并完全放弃延迟加载。你可以只关闭延迟加载在这种特定的情况:

using (var context = new MyObjectContext()) 
{ 
    context.ContextOptions.LazyLoadingEnabled = false; 

    var user = context.Users.Single(u => u.UserId == 3); 
    var role = context.Roles.Single(r => r.RoleId == 5); 

    user.Roles = new List<Role>(); // necessary, if you are using POCOs 
    user.Roles.Add(role); 

    context.SaveChanges(); 
} 

编辑

如果你想更新用户的整体角色收集我宁愿加载具有预先加载原来的角色( = Include)。反正你需要这个名单可能删除一些角色,所以你不需要等到延迟加载从数据库中获取它们:

var newRolsIds = new List<int> { 1, 2, 5 }; 
using (var context = new MyObjectContext()) 
{ 
    var user = context.Users.Include("Roles") 
     .Single(u => u.UserId == 3); 
    // loads user with roles, for example role 3 and 5 

    var newRoles = context.Roles 
     .Where(r => newRolsIds.Contains(r.RoleId)) 
     .ToList(); 

    user.Roles.Clear(); 
    foreach (var newRole in newRoles) 
     user.Roles.Add(newRole); 

    context.SaveChanges(); 
} 

而是从数据库中加载新的角色,你也可以将它们自您在示例中知道关键属性值。您还可以删除完全删除的角色,而不是清除整个集合,而不是重新添加现有角色:

var newRolsIds = new List<int> { 1, 2, 5 }; 
using (var context = new MyObjectContext()) 
{ 
    var user = context.Users.Include("Roles") 
     .Single(u => u.UserId == 3); 
    // loads user with roles, for example role 3 and 5 

    foreach (var role in user.Roles.ToList()) 
    { 
     // Remove the roles which are not in the list of new roles 
     if (!newRoleIds.Contains(role.RoleId)) 
      user.Roles.Remove(role); 
     // Removes role 3 in the example 
    } 

    foreach (var newRoleId in newRoleIds) 
    { 
     // Add the roles which are not in the list of user's roles 
     if (!user.Roles.Any(r => r.RoleId == newRoleId)) 
     { 
      var newRole = new Role { RoleId = newRoleId }; 
      context.Roles.Attach(newRole); 
      user.Roles.Add(newRole); 
     } 
     // Adds roles 1 and 2 in the example 
    } 
    // The roles which the user was already in (role 5 in the example) 
    // have neither been removed nor added. 

    context.SaveChanges(); 
} 
+0

thx Slauma。我了解我想要将新角色添加到集合user.Roles的情况。我无法理解的是我必须操纵一组角色的一般情况。例如:user.Roles包含3,5个角色;然后,我选择更新user.Roles,使其包含1,2,5(我必须删除3,并且我必须在user.Roles中添加1,2)。它是否以相同的方式工作? – frabiacca 2012-01-15 15:11:34

+1

@frabiacca:看我的编辑。 – Slauma 2012-01-15 16:06:13

+1

我有一个尝试..它的工作原理! :) thx so slauma – frabiacca 2012-01-16 22:47:06