存储库类应该在哪里?

时间:2015-12-12 23:00:39

标签: c# .net oop domain-driven-design repository-pattern

当我尝试将DDD与.NET和C#一起使用时,我通常的做法是为域模型构建一个项目,另一个用于数据访问,另一个用于应用程序本身,如ASP.NET Web API。通常涉及更多的项目,但这三个我经常使用。

我的观点是,在Domain Model项目中,我提出了所有业务规则。在那里,我定义了域类型(实体,值类型,聚合等)和存储库接口。

我的观点是,在我定义了存储库接口后,我在一个单独的项目中实现。该项目是数据访问项目。我的理由是,为了实现数据访问,我通常需要这样做的技术(如ADO.NET,EF,Dapper等)。

由于某些原因,我自己发现将这些依赖项与Domain项目结合起来是不好的形式。我喜欢Domain项目是自包含的,并且与任何技术分离。

另一方面,我有时听说过存储库可能包含业务规则,应该在Domain项目中实现。

哪种方法是对的?我的方法是将存储库实现与域项目分离,以避免将技术的依赖性耦合到域项目或允许存储库中的业务规则的方法,从而使存储库存在于Domain项目中?

哪些存储库真的应该?在域项目中与域类型一起使用还是在数据访问项目中?

4 个答案:

答案 0 :(得分:3)

你的方法是正确的。存储库应该在基础架构层中实现。

  

另一方面,我有时听说过存储库可能包含业务规则,应该在Domain项目中实现。

存储库的唯一责任应该是持久性。如果您最终在存储库中使用业务逻辑,则应该重构它们。将业务逻辑移至域模型并将存储库保留在基础结构中。

如果您在查询中有业务逻辑,那么在C#中处理它的一种简单方法是从存储库返回IQueryable<T>。然后,您可以使用LINQ在应用程序或域服务中创建查询。有些人可能会认为这是一个漏洞抽象 - 您将存储库的实施限制为与IQueryable一起使用的数据访问技术。易用性经常值得一试。

答案 1 :(得分:1)

存储库是在域和数据映射器之间进行调解的边界。我会说存储库不是关于数据访问,而只是使用数据映射器将域转换为某种数据,并且它还实现了从数据到域的反向转换。

如果您希望将它们保留为技术无关,而不是在域项目之外定义和实现它们,您可以在域项目上定义存储库接口并创建域。 [SomeTech] SomeTech 可能 EF Dapper 等等,以及您要实施技术的地方特定的存储库。

现在,您的应用项目需要引用,例如 Domain.EF 项目。

BTW,根据我自己的经验,在如何组织代码文件方面的关注点的良好分离不如解决方案在软件层方面的架构。

也就是说,如果您的项目完全使用类似于OR / M的实体框架,那么您将来更改它的可能性是微不足道的,因此,不要浪费您的时间来创建太多项目的太多项目的解决方案他们每个人都将注意力集中在代码中的关注点上。

总是有时间拆分您的项目,而错误的架构只是浪费时间。

答案 2 :(得分:1)

请记住,每个代码库,每个项目,每个域都是不同的。没有严格的规则。设计最适合您项目的代码。

  

我有时听说过存储库可能包含业务规则

如果是这样,那么它们不仅仅是存储库。从最严格的意义上讲,存储库只会将内容保存到存储器中。

现在,存储库中可能存在业务驱动的逻辑,它仍然只是持久性逻辑。在您描述的标准3层设置中,这种持久性逻辑可能需要在该层的任何其他实现中进行复制。这不是世界末日。

但它确实提出了你要问的问题。而且,正如我所说,确实没有严格的规则。您需要为您的项目确定要维护的规则,并围绕这些规则设计代码。

例如......

  • 您可以将此“业务逻辑”移动到模型或其他域代码中,并使存储库保持简单。
  • 您可以将此“业务逻辑”保留在存储库中,并在其他存储库实现中重新实现它。
  • 您可以在传统域和应用此“业务逻辑”的简单存储库之间创建一个薄层。您可以将这些视为存储库接口的域拥有包装器。这些对象的唯一目的,不是真正的商业模式,而是与存储库相关的概念逻辑类型,具体包含这种逻辑。

最后,这取决于你。没有正确的答案,除了对您的代码库最有意义的答案,并产生简单,可维护的代码。

答案 3 :(得分:1)

表示数据管理,人工交互,系统交互和问题域的对象之间的解决方案 [* 1]的表示应该存在逻辑分离(问题对象模型)。

物理分离(比如项目)完全是可选的。许多人认为这是一个很好的组织实践。

数据管理对象(例如存储库)应该只具有持久化和检索持久数据的功能,而不是业务逻辑或规则。

[* 1]包括模拟问题的对象(&#34;问题域&#34;),以及生成完整工作系统所需的所有支持对象。