2012-01-15 101 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