多对多关系,Code-First POCO,ICollection vs IList和延迟加载 [英] Many-to-Many relationships, Code-First POCO, ICollection vs IList, and Lazy Loading

查看:69
本文介绍了多对多关系,Code-First POCO,ICollection vs IList和延迟加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我的域模型是标准的User,UserRole和Role设计。

即类似于:



公共类用户
{
public int Id {...}
public virtual IList< Role>角色{...}
}

公共类角色
{
public int Id {...}
public virtual IList< User>用户{...}
}




我在我的DataContext中定义了这个


 protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove< OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove< IncludeMetadataConvention>();
modelBuilder.Entity< User>()
.HasMany(u => u.Roles)
.WithMany(r => r.Users)
.Map(userrole => {
userrole.ToTable(" UserRole");
userrole.MapLeftKey(u => u.Id," UserId");
userrole.MapRightKey(r = > r.Id," RoleId");
});
}

我有两个问题:


1)删除

如果我检索我的User对象(带有角色)并尝试删除它,我将得到数据库引用约束错误,因为EF4没有删除UserRole表中的记录。但是,如果我第一次懒加载user.Roles集合,那么就没有问题了。即在我的nUnit测试用例中
,这解决了问题。

 Assert.AreEqual(myCount,userObj.Roles.Count) ; 

 


或者,我是否需要做这样的事情?


 

 myDataContext.Entry(userObj).Reference(u => u.Roles).Load(); 

 


这是设计还是错误?我看到了其他可能与讨论相关的帖子,但我很确定我已经正确设置了"识别关系"。




http ://social.msdn.microsoft.com/forums/en-us/adonetefx/thread/726461DA-A20A-4D8F-9FC7-18308D3C1F6D

http://social.msdn.microsoft.com/论坛/ en-NZ / adonetefx / thread / 3803853b-bca9-4e20-adad-2d5dd45bd3b8


2)更新

当我尝试更新User对象时,我收到此错误:


"'User'类型的实体上的'Roles'属性是一个集合导航属性。应该使用Collection方法代替Reference方法。"  System.SystemException {System.ArgumentException}


 


这是因为我使用的是IList而不是ICollection?


有人可以解释为什么我们需要使用ICollection,如果我们确实使用ICollection,那么包装/映射回List / IList的最佳方法是什么?这是关于该主题的另一个相关主题:


http://social.msdn.microsoft.com/forums/en-us/adonetefx/thread/A70E79D9-F9AA-42E4-9396- C11FD22141FB


谢谢,


Ray


 

解决方案

嗨雷,


1)这是一个错误,在下一个版本中我们将在数据库中的级联删除中添加。目前最好的办法是将数据加载到内存中。


2)IList或任何其他实现ICollection的类型都可以。例外是要求你使用.Collection而不是.Reference,即你的代码应该是  myDataContext.Entry(userObj).Collection(u
=> u.Roles).Load();


〜罗文


Hi,

My domain model is the standard User, UserRole, and Role design.
i.e. something similar to:

public class User
{
 public int Id {...}
 public virtual IList<Role> Roles {...}
}

public class Role
{
 public int Id {...}
 public virtual IList<User> Users {...}
}


I've defined in my DataContext this

  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
   modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
   modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
   modelBuilder.Entity<User>()
    .HasMany(u => u.Roles)
    .WithMany(r => r.Users)
    .Map(userrole => {
     userrole.ToTable("UserRole");
     userrole.MapLeftKey(u => u.Id, "UserId");
     userrole.MapRightKey(r => r.Id, "RoleId");
    });
  }

I have two problems:

1) Deletion
If I retrieve my User object (with roles) and try to delete it, I will get database reference constraint error because EF4 is not deleting the record in UserRole table. However, if I first lazy load the user.Roles collection, then there is no problem. i.e. in my nUnit test case, this solved the problem.

Assert.AreEqual(myCount, userObj.Roles.Count);

 

alternatively, should I need to do something like this?

 

myDataContext.Entry(userObj).Reference(u => u.Roles).Load();

 

Is this by design, or a bug? I saw these other posts, which might be relevant for discussion, but I'm pretty sure I have properly setup the "identifying relationship".


http://social.msdn.microsoft.com/forums/en-us/adonetefx/thread/726461DA-A20A-4D8F-9FC7-18308D3C1F6D
http://social.msdn.microsoft.com/Forums/en-NZ/adonetefx/thread/3803853b-bca9-4e20-adad-2d5dd45bd3b8

2) Update

When I try to update the User object, I get this error:

"The 'Roles' property on entity of type 'User' is a collection navigation property. The Collection method should be used instead of the Reference method."  System.SystemException {System.ArgumentException}

 

Is this because I am using an IList instead of ICollection?

Can someone explain why we need to use ICollection, and if we do use ICollection, what is the best way to wrap/map back to a List/IList? Here's is another relevant thread on the topic:

http://social.msdn.microsoft.com/forums/en-us/adonetefx/thread/A70E79D9-F9AA-42E4-9396-C11FD22141FB

Thank you,

Ray

 

解决方案

Hi Ray,

1) This is a bug, in the next release we will add in a cascade delete in the database. For the moment the best thing to do is load the data into memory.

2) IList, or any other type that implements ICollection is fine. The exception is asking you to use .Collection instead of .Reference, i.e. your code should be myDataContext.Entry(userObj).Collection(u => u.Roles).Load();

~Rowan


这篇关于多对多关系,Code-First POCO,ICollection vs IList和延迟加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆