实体框架/工作单元架构问题

时间:2011-09-26 22:39:03

标签: entity-framework architecture

我对UoW,Repository Pattern等非常熟悉,但在看到Entity Framework的模式的各种实现时,我很好奇为什么有人会在他们的存储库上有Save或Add方法。如果你使用存储库来获取一个对象的新实例,我想会有人已经

public Customer GetNewCustomer()
{
    Customer customer = new Customer();
     ... any initialization code here ...
    _context.Customers.AddObject(customer);
   return customer;
}

我知道在某些设计中,你可以简单地使用

Customer customer = new Customer();

并且它没有附加到上下文的任何地方。但是我是私有构造函数的粉丝所以对Customer对象有一个单点实例化。考虑到这一点,在使用UoW模式并且在IUnitOfWork接口上仅具有此功能时,在存储库中永远不会有添加/保存方法是否有意义?

3 个答案:

答案 0 :(得分:1)

当我遵循Java中的Spring习语时,工作单元(和事务)与服务相关联。他们使用模型和持久性对象来完成请求。交易使用方面标记。

我不知道.NET是否遵循类似的想法,但它值得探索。拥有基于接口的POCO服务并让他们拥有交易。

答案 1 :(得分:1)

我认为您的解决方案不正确。这将把空客户添加到当前的工作单元中。这意味着如果后来的代码决定不以当前的工作单位来保存客户,那将会很难。

存储库具有保存实体的方法是很常见的。您正在组合域驱动设计中使用的两种模式

  • 存储库
  • 对象工厂

存储库的职责是检索或存储实体。对象工厂的责任是处理实体构建。

顺便说一下。如果存储库不是实体(这将是非常糟糕的),您的实体的私有构造函数将无法在您的存储库中访问。

答案 2 :(得分:1)

  

...永远不会有一个添加/保存方法   存储库使用UoW模式并且只具有此功能   在IUnitOfWork界面上?

是的我认为只在IUnitOfWork界面上使用Save方法才有意义。但是,我不再使用EF的存储库模式。相反,我现在使用命令的these variations&查询模式。

如果您考虑一下,EF DbContext实际上做了三件事:1。)它作为您的存储库用于读取实体状态,2。)作为您的变更实体状态的存储库,以及3.)作为UnitOfWork for跟踪多个更改并将它们组合到一个事务中以保持状态突变。

那么,为什么不将这3个职责分成3个不同的界面呢?

public interface IUnitOfWork
{
    int SaveChanges();
}

public interface ICommandEntities : IQueryEntities
{
    void Create(Entity entity);
    void Update(Entity entity);
    void Purge(Entity entity);
}

public interface IQueryEntities
{
    IQueryable<AggregateRoot1> AggregateRoot1s { get; }
    IQueryable<AggregateRoot2> AggregateRoot2s { get; }
    IQUeryable<AggregateRootN> AggregateRootNs { get; }

    IQueryable<TEntity> EagerLoad<TEntity>(IQueryable<TEntity> query, 
        Expression<Func<TEntity, object>> expression)
        where TEntity : Entity;
}

然后,您可以在DbContext类上实现这3个接口。这使得接口保持良好和隔离,并允许依赖项仅注入您需要的DbContext的那些方法。

例如,您的域名应该是持久性无知的,对吧?在这种情况下,不要在IUnitOfWork接口上提供任何域类依赖项。相反,在IoC组合根(或MVC操作过滤器)中处理IUnitOfWork。然后,您的查询和命令处理程序仅处理ICommandEntities和IQueryEntities接口。