我已经走了很多路,并在不同的项目上创建了许多存储库的实现,并且......我已经放弃并放弃了它,这就是原因。
异常的编码
您是否会针对数据库从一种技术更改为另一种技术的 1% 的可能性进行编码?如果您正在考虑您的企业的未来状态并同意这是一种可能性,那么 a) 他们必须有很多钱来承担迁移到另一种数据库技术的费用,或者 b) 您选择数据库技术是为了好玩或 c) )您决定使用的第一项技术出现了严重错误。
为什么要抛弃丰富的 LINQ 语法?
LINQ 和 EF 的开发是为了让您可以用它来做一些巧妙的事情来读取和遍历对象图。创建和维护一个可以为您提供同样灵活性的存储库是一项艰巨的任务。根据我的经验,每当我创建一个存储库时,我都会ALWAYS将业务逻辑泄漏到存储库层,以提高查询性能和/或减少对数据库的命中次数。
我不想为我必须编写的查询的每个排列创建一个方法。我还不如写存储过程。我不想要GetOrder
, GetOrderWithOrderItem
, GetOrderWithOrderItemWithOrderActivity
, GetOrderByUserId
等等...我只想获取主要实体并遍历并包含对象图,如我所愿。
大多数存储库的例子都是废话
除非您正在开发一些非常简单的东西,例如博客或其他东西,否则您的查询永远不会像您在互联网上找到的围绕存储库模式的 90% 的示例那么简单。我怎么强调都不为过!这是必须要在泥沼中爬行才能弄清楚的事情。总会有一个查询破坏您创建的经过深思熟虑的存储库/解决方案,直到那时您才开始怀疑自己,技术债务/侵蚀就开始了。
不要对我进行单元测试,兄弟
但是如果我没有存储库,单元测试怎么办?我将如何嘲笑?很简单,你不会。我们从两个角度来看:
没有存储库 - 您可以模拟DbContext
使用一个IDbContext
或其他一些技巧,但你实际上是在进行单元测试LINQ 到对象并不是实体的 LINQ因为查询是在运行时确定的...好吧,这不好!所以现在由集成测试来解决这个问题。
使用存储库 - 您现在可以模拟存储库并对中间的层进行单元测试。很棒吧?好吧,不是真的......在上面的情况下,您必须将逻辑泄漏到存储库层以使查询性能更高和/或减少对数据库的命中,您的单元测试如何涵盖这一点?它现在位于 repo 层,您不想测试IQueryable<T>
正确的?另外,老实说,您的单元测试不会涵盖 20 行的查询.Where()
条款和.Include()
是一堆关系,并再次访问数据库来执行所有其他操作,等等,等等,无论如何,因为查询是在运行时生成的。另外,由于您创建了一个存储库来保持上层持久性的无知,如果您现在想要更改数据库技术,那么抱歉,您的单元测试肯定不会保证在运行时得到相同的结果,回到集成测试。所以存储库的整个点看起来很奇怪..
2 cents
当在普通存储过程(批量插入、批量删除、CTE 等)上使用 EF 时,我们已经失去了很多功能和语法,但我也使用 C# 进行编码,因此不必输入二进制。我们使用 EF,因此我们可以使用不同的提供程序,并以一种良好的相关方式处理对象图。某些抽象有用,有些则无用。