为什么实体框架需要ICollection来进行延迟加载?

时间:2010-05-19 15:21:55

标签: entity-framework domain-driven-design lazy-loading

我想写一个丰富的域类,比如

public class Product    
{    
   public IEnumerable<Photo> Photos {get; private set;}    
   public void AddPhoto(){...}    
   public void RemovePhoto(){...}
 }

但是实体框架(V4代码第一种方法)需要一个ICollection类型来进行延迟加载!上面的代码不再按设计工作,因为客户端可以绕过AddPhoto / RemovePhoto方法并直接在ICollection上调用add方法。这不好。

public class Product    
{    
   public ICollection<Photo> Photos {get; private set;} //Bad    
   public void AddPhoto(){...}    
   public void RemovePhoto(){...}    
 }

尝试使用EF4实现DDD真的很令人沮丧。他们为什么选择ICollection进行延迟加载?

我怎样才能克服这一点? NHibernate能为我提供更好的DDD体验吗?

3 个答案:

答案 0 :(得分:21)

我想我找到了解决方案......有关详细信息,请参阅此处:http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/47296641-0426-49c2-b048-bf890c6d6af2/

基本上,您希望保护ICollection类型并将其用作公共IEnumerable的支持集合

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,访问必须是公共的或受保护的。

答案 1 :(得分:5)

您无法插入IEnumerable。这适用于EF,就像它对客户一样。但是,您不必使用ICollection;您可以使用IList或其他可写类型。我对两全其美的建议是向您的客户公开DTO而不是实体。

答案 2 :(得分:2)

您可以使用ReadOnlyCollection(Of T)

解决此问题
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<T> =&gt; IList<T>

希望这就是你要找的东西。