工作单元和存储库模式对大型项目非常有用吗?

meh*_*rif 25 c# domain-driven-design unit-of-work repository-pattern

我正在使用ASP.NET Webforms + EF4开始一个新的Web项目.我正在尝试按照本教程应用具有工作单元模式的存储库模式:http://www.dotnetage.com/publishing/home/2011/07/05/6883/the-repository-pattern-with-ef -code先dependeny喷射在-ASP净mvc3.html

我想我有了这个想法,但我的问题是,当我在模型中创建一个新对象时,我是否还必须在工作单元的IDALContext中定义该对象?这不是一个快速发展的手?此外,如果您与多个开发人员合作,并且如果您不希望其他开发人员看到您的DAL,您如何管理它?因为在我理解的模式中,当您在模型中创建新对象时,您还必须在本教程的IDALContext中定义它.对不起,我很困惑.

Jur*_*uri 99

现在,第一个问题应该是,为什么我需要一个存储库或工作单元模式呢?难道我不能只使用控制器的EF上下文,具有直接编写我需要的查询并返回数据的全部功能吗?
答:你可以,但真正的意图是可测试性,从而提高质量,更易维护的代码.如果您将数据访问分开并将其集中在一个地方,则可以在测试期间将其模拟出来.这允许您对控制器中定义的逻辑进行单元测试,而无需有效地写入数据存储.

在开始使用工作单元之前,只需使用Repository模式.这基本上抽象了给定实体的数据访问.因此,您可以定义Filter(),All(),Update(..),Insert(..),Delete(...)以及最后Save()等方法.实际上,大多数这些都可以很容易地抽象到 BaseRepository<TEntity>类中,这样最终你只需要在极少数情况下创建一个具有特殊行为的新存储库.否则它会像BaseRepository<Person> personRepo = new BaseRepository<Person>()BaseRepository<Address> addressRepo = new BaseRepository<Address>()等等.

为什么需要工作单位?
工作单元表示在特定周期内完成的所有操作,通常在每个Http请求的Web环境中.这意味着当新请求进入时,您实例化一个新的工作单元,添加新东西,更新或删除它,然后通过调用.save()或者.commit()..whatever "提交"更改.实际上,如果你仔细看看Entity Framework DbContext(或ObjectContext),它们已经代表了某种工作单元.
但是,如果您想进一步抽象它,因为您不一定希望在控制器类中使用您的EF上下文(记住:可测试性),那么您创建一个UoW来对您的存储库进行分组,并确保它们共享相同的EF上下文实例.您也可以通过DI容器(依赖注入容器)来实现后者.

问题:在大型项目中它是否有用?:
当然,特别是在项目中.这一切都是为了保持责任分离(数据访问,业务逻辑,域逻辑),从而使事情变得可测试.


sai*_*ama 19

Martin Fowler将存储库的角色描述为:"存储库在域和数据映射层之间进行调解,就像内存域对象集合一样".实体框架4.1公开的内容就是这种意义上的存储库.EF也有内置的统一工作.所以我的建议是忽略你在问题中提到的博客文章.

像这样的代码不仅无用或无用而且危险,因为你的代码没有任何好处,而是依赖!

public interface IUnitOfWork:IDisposable
{
    int SaveChanges();
}

public interface IDALContext : IUnitOfWork
{
    ICategoryRepository Categories { get; }
    IProductRepository Products { get; }
}
Run Code Online (Sandbox Code Playgroud)

要回答你的问题,在域和数据映射层之间进行一些抽象调整,就像内存域对象集合一样,是"大"项目的必需品.在引擎盖下使用UnitOfWork机制可以帮助将业务逻辑与访问某些数据访问抽象分离.

TL; TR; Repository和UnitOfWork可以帮助您,但不要像给定的博客文章那样应用它.

  • +1指出EF上下文既是存储库又是工作单元,开箱即用.理解模式的一个关键是能够在代码中识别它们,即使没有命名为模式的类. (6认同)

Mos*_*osh 5

软件设计模式旨在解决具有正确上下文的特定问题,如果使用不当,它们将导致额外的不必要的复杂性,而不会提供任何价值。

那么,存储库模式旨在解决哪些问题?

1-最小化重复查询逻辑:在大型应用程序中,您可能会发现在许多地方重复了许多复杂的LINQ查询。在这种情况下,您可以使用存储库模式来封装这些查询并最大程度地减少重复。

2-更好地分离关注点:想象一个复杂的查询,以获取给定类别中的最畅销课程,其中涉及急切的加载,加入,分组,过滤等。

当在服务/控制器中实现如此大的复杂查询时,最终将得到繁琐的服务/控制器。这些类很难进行单元测试,因为它们需要大量的嘈杂测试。您的单元测试变得漫长,繁琐且无法维护。

如果您遇到此问题,也许您可​​以考虑使用存储库模式。在此示例中,我们可以封装复杂的查询以在存储库中获得最畅销的课程:

courseRepository.GetTopSellingCourses(int categoryId, int count);
Run Code Online (Sandbox Code Playgroud)

这样,您的服务/控制器将不再处理急切的加载,联接,分组等工作。它们将委托给存储库。请记住,急切的加载,联接和分组等都是查询逻辑,属于您的数据访问层,而不是您的服务或表示层。

3- 将您的应用程序体系结构与持久性框架分离:当您直接在应用程序中使用实体框架类(例如DbContext,DbSet等)时,您的应用程序与实体框架紧密耦合。如果您打算将来某个时候切换到其他O / RM,或者甚至是使用不同模型的较新版本的Entity Framework,则可能必须修改应用程序的许多部分,这可能会导致应用程序中出现新的错误。您可以使用存储库模式将应用程序体系结构与持久性框架(例如实体框架)分离。这样,您将可以自由更改为其他O / RM,而对应用程序的影响最小。

观看此视频以了解更多详细信息:

https://youtu.be/rtXpYpZdOzM