2011-03-01 53 views
1

嗨我试图在EF4上创建一个通用库。我希望创建一个存储库类,以保持ObjectContext自身的状态,而不是使用不同的Repository & UnitOfWork实现。我的界面如下所示:通用库设计

/// <summary> 
/// Contract for base generic repository 
/// </summary> 
public interface IRepository 
{ 
    ActionResult SaveData<TEntity>(TEntity entityObj, bool commitTransaction) where TEntity : IEntity, new(); 

    ActionResult SaveData<TEntity>(ICollection<TEntity> entityObjects, bool commitTransaction) where TEntity : IEntity, new(); 

    ActionResult DeleteData<TEntity>(TEntity entityObj, bool commitTransaction) where TEntity : IEntity, new(); 

    ActionResult DeleteData<TEntity>(ICollection<TEntity> entityObjects, bool commitTransaction) where TEntity : IEntity, new(); 

    ICollection<TEntity> SelectAll<TEntity>() where TEntity : IEntity, new(); 
    ICollection<TEntity> SelectByCondition<TEntity>(Func<TEntity, bool> condition) where TEntity : IEntity, new(); 
} 

ActionResult是一个类,它告诉我特定的事务是否成功执行。现在我不想维护仓库之外的事务状态。所以每次保存/删除我们都可以传递布尔值。第一次,事务对象可以在内部检查,然后当我打电话给我的最后一个事务时,我可以发送committransaction true,这将调用SaveChanges()函数。

我的问题是:这种方法设计好吗?我可以面对什么问题?

回答

3

我看到这个实现有很多问题。

  • 明确告诉每个保存和删除操作是否提交都很麻烦并且容易出错。只是意外地将一个操作设置为假,而您的休息原子。控制交易不应该在该级别完成。
  • SelectByCondition需要一个Func<T, bool>谓词,这意味着必须在内存中加载和过滤完整的数据库表。更好的设计是使用表达式树。
  • 你说你定义了一个“存储库类,它将自己维持在ObjectContext的状态”,但实际上你定义了一个工作单元:-),因为存储库被用于单一类型的对象。
  • 每种方法都采用TEntity类型的参数,而这在接口级更适合,因为那样你就会遵循存储库设计模式。例如:IRepository<TEntity>。这样的设计会使使用类型安全。

看一看this article。它描述了一个(相当抽象的)实现作品和存储库单元的方式,同时允许你对它们进行LINQ查询并允许它们成为单元可测试的。

1

您基本上已经创建了一个混合工作单元和存储库接口,从而打破了SRP。我建议你坚持通常通过IoC容器注入到仓库的工作单元。你仍然可以使用通用的Repository。这是一个众所周知的模式,特别是围绕EF提供了大量的社区样本(请参阅单元测试EF的链接)。

在可能的情况下使用常见模式而不是烘烤自己的模式,将会为现在或将来的团队提供更好的服务。

+0

+1。我完全同意。 – Steven 2011-03-01 19:04:27