C# EF5中的UOW和存储库模式

C# EF5中的UOW和存储库模式,c#,asp.net-mvc,entity-framework-5,C#,Asp.net Mvc,Entity Framework 5,这是关于我在这里发现的一些实体框架材料的一些困惑: 在本页中,它解释了如何使用存储库包装dbcontext,以及如何使用工作单元类包装存储库: 但是,在本页上,它指出dbcontext已经是UOW模式和repository模式的组合: 因此,如果dbcontext已经解决了这些模式所解决的问题,那么为什么要用EF5重新实现这些模式呢 此外,在本教程中,UnitOfWork类似乎没有显示UOW应该提供的任何好处。例如,它声明:“这样,当一个工作单元完成时,您可以在该上下文实例上调用SaveC

这是关于我在这里发现的一些实体框架材料的一些困惑:

在本页中,它解释了如何使用存储库包装dbcontext,以及如何使用工作单元类包装存储库:

但是,在本页上,它指出dbcontext已经是UOW模式和repository模式的组合:

因此,如果dbcontext已经解决了这些模式所解决的问题,那么为什么要用EF5重新实现这些模式呢

此外,在本教程中,UnitOfWork类似乎没有显示UOW应该提供的任何好处。例如,它声明:“这样,当一个工作单元完成时,您可以在该上下文实例上调用SaveChanges方法,并确保所有相关的更改都将得到协调。”


但它似乎只是毫无理由地包装dbcontext。我想我错过了什么。我看不到在这个实施过程中有任何协调。。。如果出现问题,如何“回滚”呢?

EF的问题是,它公开的OUW或存储库功能中没有业务逻辑。如果您调用SaveChanges,它将很高兴地保存所有更改。然而,有一个要求是,当添加(比如)小部件时,必须为小部件添加一个Frobber,这是因为您运气不好(除非涉及FK依赖关系)。对于未在数据关系中表示的任何业务逻辑位,EF开箱即用不会强制执行它


要实施这种类型的逻辑,您必须围绕EF上下文构建某种OUW/存储库/两者。据我所知,这是你这么做的唯一原因。

我已经写了大量关于这方面的文章,但为了您的利益,我将进行总结。是的,实体框架已经实现了UoW(
DbContext
)和repository(
DbSet
)模式。再次实施它们没有任何好处。事实上,这会带来很大的危害,因为它会显著增加项目的维护开销

为什么微软在入门教程中包含了这一点?老实说,我不确定,但这是一个困扰无数新MVC开发人员的错误,包括我刚开始的时候


某种抽象有好处,例如您的项目不依赖于任何一种获取数据的特定方式。然而,这个抽象应该返回您的操作所需要的特定数据,不多也不少。由于没有更好的词,我将其称为“服务”,尽管微软通过SOA将一个完全不同的含义嫁接到了这个词上。简单地说,这就像您正在创建一个应用程序使用的API,就像您正在创建一个web API,完全基于代码(不需要实际的HTTP连接)。然后进入项目可以引用的DAL层(类库或类似层)。

不要使用其他UoW/存储库抽象层

正如OP正确指出的那样,实体框架(类似于NHibernate和其他ORM)已经为您提供了数据库的抽象,并提供了一个事务性的“工作单元”和“存储库”

额外的UoW/存储库抽象层是一种反模式,应该不惜一切代价避免。它有许多问题,其中最重要的是:

  • 它们阻止您使用底层ORM的全部功能(惰性负载、急切负载、复杂查询等)
  • 如果它们想要提供简单CRUD之外的任何附加好处,它们将是泄漏的(即反映底层ORM中存在的功能)
但是,但是,但是…

我需要能够通过模拟我的存储库进行单元测试

不,你没有。只需使用一个包含特定于测试内容的数据库即可。如果希望更快,请使用内存中的数据库(例如SQLite…)

EF不强制执行未在数据关系中表示的业务逻辑。。。要实施这种类型的逻辑,您必须围绕EF上下文构建某种OUW/存储库/两者

不,你不应该。在基础设施抽象层(如工作单元或存储库)中实现业务逻辑是完全错误的

  • 有价值的业务逻辑属于域实体、域服务、域命令或长期运行的业务流程、传奇
  • 简单的验证(即非
    null
    ,介于
    x
    y
    之间的值)没有:这些应该在系统接口边界处解决
还请注意,没有任何有价值的业务逻辑的简单CRUD风格的操作不需要经历所有的“层环”,即避免这种模式:

  • 数据库→ 无行为的实体→ DTO→ 视图模型→ 看法
  • 编辑字段
  • 看法→ 视图模型→ DTO→ 无行为的实体→ 数据库
  • 只需将它直接从ORM加载到控制器中视图所需的“视图模型”形状中,然后直接从控制器保存它

    关于抽象

    像这样不必要的抽象和层箍是邪恶的。它们会混淆你的代码,束缚你的手脚,泄漏,增加你的代码大小,从而增加你代码中的错误数量,而不提供任何附加值

    当抽象为您提供附加值时使用抽象,例如,当您在解决交叉关注点、捕获/管理体系结构中重复出现的模式方面需要它们时


    为了抽象而创建抽象是浪费时间。

    工作单元和存储库模式与实体框架无关。这是一种设计模式。因此,它被用来使您的代码更具可读性、可重用性和效率,并且这些模式也被用来实现Singleton(一次对象)