C# 使用或不使用ORM存储库

C# 使用或不使用ORM存储库,c#,entity-framework,orm,domain-driven-design,ddd-repositories,C#,Entity Framework,Orm,Domain Driven Design,Ddd Repositories,有很多声音说,在这个ORM时代,不再需要存储库。最近我自己也在想,他们的论点对我来说通常是有道理的 在我的新项目中,使用EF Core,我想我尝试了无存储库的方法,使事情变得更加简单和直接。毕竟,简单总是好的 事情进展得很顺利,直到我意识到我经常写这样的东西(这不是一个真正的聚合,只是一个人工的例子): 好的,所以每次我需要得到一个汇总,我需要写下这句话,有机会,有时/有人会忘记包括一个重要的参考 如何将此代码放入助手类 class InvoiceHelper { public Invoic

有很多声音说,在这个ORM时代,不再需要存储库。最近我自己也在想,他们的论点对我来说通常是有道理的

在我的新项目中,使用EF Core,我想我尝试了无存储库的方法,使事情变得更加简单和直接。毕竟,简单总是好的

事情进展得很顺利,直到我意识到我经常写这样的东西(这不是一个真正的聚合,只是一个人工的例子):

好的,所以每次我需要得到一个汇总,我需要写下这句话,有机会,有时/有人会忘记包括一个重要的参考

如何将此代码放入助手类

class InvoiceHelper
{
  public Invoice FindById(int id) {...}
}
这不只是一个伪装的存储库的开始吗?因此,即使使用ORM,我仍然觉得存储库有点有用

其他人如何做这些事情,并且在没有存储库的情况下仍然看起来很快乐

一些讨论无存储库方法的文章:


如果您相信经验法则“不要模仿您不拥有的东西”,我看不出您如何能够在测试中用ORM功能代替模仿或存根,而不使用类似于存储库的抽象

存储库是应用程序和存储之间非常重要的seam适配器(用六边形的说法)

是的,您需要创建一个帮助器来考虑某些数据获取行为,这一事实正好说明了这一重要性

[编辑]对“无回购”文章的思考

通常,大多数“存储库反弹”是对存储库和UoW滥用的过度反应,其根源在于对模式背后的原始原因的集体遗忘

  • “为什么要隐藏一个完美的框架?”-EF不是! 例如,其中一篇文章提到的
    IDbSet
    是一个不断泄漏的抽象,从它的名字到它的所有扩展方法。另请参见下文对“完美框架”提供的
    Update()
    等方法的误用和误解

    相比之下,原始存储库模式的要点是成为一个简单的3方法集合,就像你不会出错的抽象一样
    Add()
    Remove()
    和一些Get方法是我们所需要的,而不是整个框架的全部功能

  • “存储库并没有使测试变得更容易”:是的,确实如此!依赖项的契约越小,就越容易进行推理、测试和调试。又叫接吻

  • “1.性能–排序/筛选:Microsoft旧的(2013年)Rep/UoW实现有一个名为GetStudents的方法,返回IEnumerable。这意味着任何筛选或排序都将在软件中完成,效率低下。”

    真的吗?多年前编写的Microsoft教程示例代码的糟糕之处是整个模式的#1缺点?当您只需要在repo实现中创建一个方法时,它可以根据您的需要进行优化

  • 代表/UoW将使用EF Core的更新方法更新实体-谁说?又是一个稻草人。我已经使用这些模式10多年了,从未需要过这种方法。SaveChanges()一直是一种方法

  • Rep/UoW的魅力来自这样一种观点:您可以编写一个通用存储库,然后使用它来构建所有子存储库

    绝对不是。这不是最初模式的一部分,甚至从DDD采用的早期起,在社区中基本上被认为是一种反模式

  • “选项2-DDD样式的实体类” aka进行数据访问的域类。。。这摧毁了坚持和无知。在我看来,这不是个好主意

几乎每一个论点我都可以滔滔不绝,但要点是:


如果你要责怪某个模式,那么就要充分理解其基本原理,而不是因为你不喜欢某个被复制粘贴、被一代又一代的开发人员视为无用的坏实现。

如果你相信经验法则“不要嘲笑你不拥有的东西”,我不明白,如果没有类似于存储库的抽象,如何在测试中用ORM功能替换模拟或存根

存储库是应用程序和存储之间非常重要的seam适配器(用六边形的说法)

是的,您需要创建一个帮助器来考虑某些数据获取行为,这一事实正好说明了这一重要性

[编辑]对“无回购”文章的思考

通常,大多数“存储库反弹”是对存储库和UoW滥用的过度反应,其根源在于对模式背后的原始原因的集体遗忘

  • “为什么要隐藏一个完美的框架?”-EF不是! 例如,其中一篇文章提到的
    IDbSet
    是一个不断泄漏的抽象,从它的名字到它的所有扩展方法。另请参见下文对“完美框架”提供的
    Update()
    等方法的误用和误解

    相比之下,原始存储库模式的要点是成为一个简单的3方法集合,就像你不会出错的抽象一样
    Add()
    Remove()
    和一些Get方法是我们所需要的,而不是整个框架的全部功能

  • “存储库并没有使测试变得更容易”:是的,确实如此!依赖项的契约越小,就越容易进行推理、测试和调试。又叫接吻

  • “1.性能–排序/筛选:Microsoft旧的(2013年)Rep/UoW实现有一个名为GetStudents的方法,返回IEnumerable。这意味着任何筛选或排序都将在软件中完成,效率低下。”

    真的吗?这个
    class InvoiceHelper
    {
      public Invoice FindById(int id) {...}
    }