在我工作的公司,我被责令更新旧的MVC应用程序并为SQL数据库实现存储库模式。我已经使用Entity Framework Database-First创建了数据库的上下文,并获得了23个实体。
我需要为每个实体创建一个存储库还是为上下文实现一个通用存储库?我问这个问题是因为我在搜索互联网时发现了以下内容:
每个域一个存储库
您应该将存储库视为内存中域对象的集合。如果您要构建一个名为Vega的应用程序,则不应具有以下存储库:
public class VegaRepository {}
来源:Programming with Mosh: 4 Common Mistakes with the Repository Pattern
通用存储库是否适用于实体框架数据库优先?这是因为我在搜索互联网时发现了以下内容:
实体框架
请注意,只有在先使用代码映射POCO的情况下,存储库模式才有用。否则,您将改为通过实体破坏抽象(=则存储库模式不是很有用)。如果您想为您建立基础,则可以阅读本文。
答案 0 :(得分:7)
首先,如果您使用的是完整的ORM(例如Entity Framework或NHibernate),则应避免实现存储库和工作单元的附加层。
这是因为; ORM本身公开了通用存储库和工作单元。
对于EF,您的DbContext
是工作单位,DbSet
是通用存储库。对于NHibernate,它本身就是ISession
。
在相同的现有存储库上构建通用存储库的新包装是重复的工作。为什么要重新发明轮子?
但是,有人认为直接在调用代码中使用ORM存在以下问题:
除上述所有内容外,其他普遍讨论的问题是“如果我们决定将来更改ORM,该怎么办”。这不是决策时的重点,因为:
考虑到上述四个问题,即使您使用的是完整的ORM,也可能有必要创建存储库-这是根据情况决定的。
即使在这种情况下,也必须避免使用通用存储库。它被认为是反模式。
为什么通用存储库是反模式的?
GetById()
,标识符类型可能不同。我建议您阅读以下(1,2,3,4,5)文章,这些文章解释了为什么通用存储库是反模式。这个other答案通常讨论存储库模式。
所以,我建议:
无论如何,请勿将通用存储库暴露给调用代码。
此外,请勿从具体存储库返回IQueryable
。这违反了存储库存在的基本目的-抽象数据访问。通过将IQueryable
暴露在存储库之外,许多数据访问决策都会泄漏到调用代码中,并且存储库失去了对其的控制。
我需要为每个实体创建一个存储库还是为上下文实现一个通用存储库
如上所述,为每个实体创建存储库是更好的方法。请注意,存储库最好返回域模型而不是实体。但这是另一个讨论的话题。
通用存储库是否适用于EF Database First?
如上所述,EF本身公开了通用存储库。在上面再建一层是没有用的。您的图片在说同样的话。