2012-01-15 7 views
17

私は1年以来EF4を使用していましたので、私は実際にその専門家ではありません。 save nの更新に関して多対多の関係を使用することに疑問を抱いています。エンティティフレームワークの多対多リレーションシップ:仮想かどうか

既存の多対多リレーションシップを更新するための1つのソリューションが「仮想」プロパティを宣言しないように、stackoverflowのどこかで読んでいます(私はURLをもう見つけられません)。しかし、もしこのようにすれば、エンジンは読み込みが容易なデータを読み込むことができません。

理由を教えてもらえますか? Otherwire、このテーマについていくつかのクールなドキュメントを見つけるのを助けてくれますか?

THX

あなたは(ユーザー3に役割5を与える例として)多対多の関係をこのように更新することができ

答えて

56

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コレクションはvirtualとして宣言されている場合user.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

+1

@frabiacca:私の編集を参照してください。 – Slauma

+1

私は試して..それは動作します! :) thx so much slauma – frabiacca

関連する問題