【问题标题】:Why does the entity framework need an ICollection for lazy loading?为什么实体框架需要一个 ICollection 来进行延迟加载?
【发布时间】:2010-05-19 15:21:55
【问题描述】:

我想写一个富域类如

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 体验?

【问题讨论】:

  • 自己想弄清楚这一点。我知道要走的路就是你描述的路。但是如何?现在也可以在 EF 4.1 中使用吗?还是您找到了解决方案?

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


【解决方案1】:

我想我找到了解决方案...有关详细信息,请参阅此处: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 并且访问必须是公共的或受保护的。

【讨论】:

  • 仅供参考,NHibernate 要求您使用 IList,它实现了 ICollection,因此您必须对 NHibernate 使用相同的技巧。
  • 这是这个答案的解决方案吗?
  • 你赢得了赏金。 :) 享受吧!
  • 同上@hazzik。如果您使用存储库或只是尝试编写将由 EF 转换为 SQL 语句的 LINQ 表达式,并尝试使用公共 IEnumerable,它将不起作用....该属性未映射且 LINQ to Entities 不不支持。
  • @Kevin - IEnumerable 与 NHibernate 配合得很好,并且可以将集合映射到私有支持字段以实现所需的结果。查询违背公共 IEnmerable {get}
【解决方案2】:

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

【讨论】:

  • 确实如此。公开 DTO 并选择性地从这些 DTO 生成视图模型是我选择的路径。我认为太多人被吓跑了,但听起来他们需要编写多少代码才能完成它。
  • 我知道这是一篇旧帖子,但你能详细说明一下这个答案吗?
  • @Rushino:你的公共接口是一个合约。如果第三方与它集成,它是不可变的,您无法更改它。但是您可能想发展您的数据库,对吧?您的 EF 模型主要与您的数据库匹配,因此您也需要改进它。所以使用单一责任主体:使用一种类型,一个 DTO,来定义你的公共接口。使用不同的类型(实体)来处理数据库映射到可以/可能更改的架构。
  • 你有例子吗?我很形象,我相信这会帮助其他人。
【解决方案3】:

您可以使用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&lt;T&gt; => IList&lt;T&gt;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2023-03-09
    • 2013-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多