关于域驱动设计:为什么实体框架需要ICollection来进行延迟加载?

Why does the entity framework need an ICollection for lazy loading?

我想写一个富域类,比如

1
2
3
4
5
6
public class Product    
{    
   public IEnumerable<Photo> Photos {get; private set;}    
   public void AddPhoto(){...}    
   public void RemovePhoto(){...}
 }

但是实体框架(v4 code first方法)需要ICollection类型才能进行延迟加载!由于客户端可以绕过addphoto/removephoto方法并直接在ICollection上调用add方法,因此上述代码不再按设计方式工作。这不好。

1
2
3
4
5
6
public class Product    
{    
   public ICollection<Photo> Photos {get; private set;} //Bad    
   public void AddPhoto(){...}    
   public void RemovePhoto(){...}    
 }

尝试用EF4实现DDD真的让人沮丧。为什么他们选择iCollection作为懒惰加载?

我怎样才能克服这个问题?NHibernate能给我提供更好的DDD体验吗?


我认为我找到了解决方案…请参阅此处了解更多详细信息:http://social.msdn.microsoft.com/forums/en-us/adodonentityframework/thread/47296641-0426-49c2-b048-bf890c6d6af2/

实际上,您希望使ICollection类型受保护,并将其用作公共IEnumerable的支持集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Product
{

   // This is a mapped property
   protected virtual ICollection<Photo> _photos { get; set; }

   // This is an un-mapped property that just wraps _photos
   public IEnumerable<Photo> Photos
   {
      get  { return _photos; }
   }

   public void AddPhoto(){...}
   public void RemovePhoto(){...}

}

要使延迟加载工作,类型必须实现ICollection,并且访问必须是公共的或受保护的。


不能插入到IEnumerable中。这和你的客户一样适用于英孚。不过,您不必使用ICollection;您可以使用IList或其他可写类型。我的建议是最好地利用这两个方面,向客户公开DTO,而不是实体。


您可以通过使用readOnlyCollection(of t)来克服这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Product    
{  
    private IList<Photo> _photos;  
    public IList<Photo> Photos {
        get
        {
            return _photos.AsReadOnly();
        }
        private set { _photos = value; }
    }
    public void AddPhoto(){...}    
    public void RemovePhoto(){...}    
}

编辑:ICollection=>IList

希望这就是你想要的。