存储库模式设计注意事项

时间:2010-06-19 10:07:59

标签: .net entity-framework repository design-patterns

我目前正在.NET应用程序中设计/实现存储库模式。经过多天的研究,我觉得我已经接近了,但是那里真的有很多想法和意见,我希望能得到一些人的想法,如果你已经自己实现过,他们可能会有任何设计方面的考虑。所以......

所以我面临的主要设计问题是...... Generic Vs Specific Repositories?这方面有很多东西,我已经对此做了很多思考,但我还是犹豫不决。我将实现一个IRepository接口和Repository基类。然后决定是否保留这样的存储库实现,或者将Repository类作为抽象类并通过特定的存储库扩展它,以便:

public Repository<T> Repository : IRepository<T>
instantiated as: Repository<Customer> CustomerRepository = new Repository<Customer>

public CustomerRepository CustomerRepository : Repository<T>, ICustomerRepository
instantiated as: CustomerRepository CustomerRepository = new CustomerRepository()

最初,我绝对是针对具体实施的。代码重用的数量和使用通用存储库的接口和类的数量减少是一个很大的优点,但我认为它定义的合同太宽。允许外部对象以几乎任何方式查询数据访问层可能会导致各种性能和优化问题(DBA如何知道哪些查询在DB上运行而不需要梳理整个代码......可能会到UI层!!!)。这引导我到特定的存储库,它可以从抽象的BaseRepository继承以利用代码重用,同时仍然通过GetCustomerByName()等方法定义一个狭窄的契约。

我认为一个很好的解决方案,但我最终的设计也使用了通用存储库模式以及规范模式。我真的很喜欢,因为它允许将实体上的查询封装在类中。非常优雅,确保查询管理,而不是免费销售!但有几点需要注意......

1)规范的使用是否限制了移动到另一个数据源的自由度?如果数据源支持LINQ,则规范模式似乎很容易被利用到存储库中。所以我们的存储库方法就像:

IEnumerable<T> Query(ISpecification<T> specification);

但是,如果我们想使用较旧的ADO.Net 2.0提供程序创建存储库,该怎么办呢?现在不能以某种方式将查询转换为存储库中的SQL查询吗?或者整个客户表需要被读入内存,因此在匹配可以返回到聚合之前需要检查每个客户。这对我们来说是一个问题......我们有一个运行MySQL数据库的客户端支持.NET 4.0,但是另一个客户端运行的日期DB2数据库只有.NET 2.0提供者。

2)以及在每个实体的CRUD任务可能不是标准的情况下怎么办?即。也许客户不能被删除......也许某些其他实体的创建不遵循其他实体的正常创建模式?如何使用通用存储库来处理它。我确实喜欢使用规范模式的通用存储库的简化设计,但如果不支持,我将回到特定的存储库。对不起,啰嗦了......但是听到人们的想法会很棒吗?

我还想实现工作单元和DI,但我想在继续前进之前完成我的存储库设计。

2 个答案:

答案 0 :(得分:1)

也许我错了,但在查看您的解释时,我没有看到任何特定于存储库模式的内容。您的示例由简单的DAO涵盖 另外,如果您的唯一问题是针对不同客户的rdbm不同,您应该能够为您的ORM库提供两个不同的confs(如果您使用的话)。

为什么不选择简单的DAO? 在这里查看例如http://www.springframework.net/doc-latest/reference/html/nh-quickstart.html(标题42.3.3)

PS:不要让Patterns控制你,你不是他们的设计师: - )

修改 以下是关于此类问题的讨论Repository Pattern vs DAL

答案 1 :(得分:0)

我的理解是,存储库模式就像域内可以添加和接收的对象的内存集合。然后,存储库会隐藏域中的实际持久性和数据特定代码。然后,域可以构造要发送到存储库以进行操作的查询。接口定义域与存储库的契约,然后可以实现不同的存储库来隐藏下面的持久性模型。

这不是我上面谈到的内容吗?显然,删除使用Get方法查询存储库的能力会远离能够查询存储库的客户端的存储库定义,但我认为整体概念仍然相同。即使您发送给我的链接也将其DAO称为存储库...

我猜这是从你发送的第二个链接开始的,那里似乎存在大量关于存储库和DAL的重叠(和混淆???)以及它们是否是相同的东西以及它们在哪里发散。

无论我的实现是实际存储库还是仅仅是DAL,使用规范是否会限制我使用支持LINQ的数据持久性技术? (此外,LINQ具有稍微不同的能力,具体取决于它是LINQ2SQL还是LINQ2Whatever,这是否会导致数据访问要求从Repository / DAL泄漏?如果提供了通用DAL /存储库,如何才能实现覆盖与特定实体相关的存储库中的特定持久性问题?