使用依赖注入时,多个数据库上下文与具有存储库模式的UnitofWork

时间:2019-01-29 23:39:20

标签: entity-framework repository-pattern dbcontext unit-of-work

我正在处理具有多个模块的应用程序。我在同一数据库中的不同架构下为不同模块创建了表,在默认架构中创建了所有与用户相关的表。阅读更多关于dbcontext,工作单元和存储库模式的信息后,我感到更加困惑。我开始创建一个dbcontext,并意识到一个登录的用户只需要很少数量的表,但是通过调用构造函数,它将所有内容带入内存。后来我想到创建多个dbcontext,但是我必须在所有dbcontext中包括与用户相关的表。

作为第三个选择,我开始使用unitofwork和存储库模式。许多文章告诉我们,这只是使用DBContext和DBSet在EF之上的另一种抽象。我仍然继续工作,意识到我将拥有数百个存储库,一旦将它们全部添加到unitofwork中并调用了构造函数,所有内容都会再次加载到内存中。我完全困惑哪种方法最适合我的需要。每个控制器只需要特定的表存储库和用户表存储库即可进行CRUD操作,但是通过执行上述步骤,是否会导致性能问题?

我的工作单位如下

using DemoApp.Core;
using DemoApp.Core.Repositories;
using DemoApp.Persistence.Repositories;

namespace DemoApp.Persistence
{
    public class UnitOfWork : IUnitOfWork
    {
        private readonly DemoAppContext _context;
        public UnitOfWork(DemoAppContext context)
        {
            _context = context;
            Ones = new OneRepository(_context);
            Twos = new TwoRepository(_context);
        }
        public IOneRepository Ones { get; private set; }
        public ITwoRepository Twos { get; private set; }

        public int Complete()
        {
            return _context.SaveChanges();
        }
        public void Dispose()
        {
            _context.Dispose();
        }
    }
}

还有控制器

using DemoApp.Core;
using DemoApp.Core.Domain;
using DemoApp.Persistence;
using System;
using System.Linq;
using System.Web.Mvc;

namespace DemoApp.Controllers
{
    public class HomeController : Controller
    {
        private readonly IUnitOfWork _unitOfWork;
        public HomeController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }
        public ActionResult Index()
        {
            var result = _unitOfWork.Ones.GetAll();
            return View(result);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

只有一个大的上下文不会在构造时将实体加载到内存中,但会解析实体映射,这在非常大的上下文中可能需要几秒钟的时间才能进行首次加载。有界上下文适用于非常大的系统,您可以在其中划分相关实体,或将“繁重”或对时间敏感的实体与主要使用上下文分开。

我使用带有受限上下文的模式,该模式使用键入到相关上下文的属性来标记哪些实体类型配置适用于哪个上下文。这适合使用较小的只读适用实体定义。不过,我只真正推荐用于非常大的实体集。通过利用延迟执行和.Select()表达式仅提取需要的数据,通常不需要使用多个有界的实体声明。

使用工作单元和存储库模式的争论主要是围绕启用单元测试。我不建议使用通用存储库(每个实体的存储库),而是以与使用控制器模式相同的方式来使用存储库模式。每个存储库为应用程序的一个区域提供服务,该方法具有检索,创建和删除与该区域相关的实体的方法。将存储库绑定到单个实体会导致大量样板代码,或不适用于所有实体的通用操作。它使您的代码不那么灵活,最终更难阅读。在大多数情况下,您应该利用实体之间映射的关系,以便单个存储库可以管理例如特定屏幕的所有相关实体的检索和操作,而不是在大量不同的存储库之间进行切换以尝试加载相关数据。我使用Mehdime的DbContextScope UoW模式,因为它促进了跨存储库/帮助器的读/写和只读作用域,并且不需要将dbcontext / UoW包装器注入存储库。这样就可以在请求中具有多个UoW范围,而不是将DbContext / UoW实例限定在请求范围内,或者在容器支持的情况下手动更改生存期范围。无论如何,都值得一看。 Mehdime的实现适用于EF 6.x,而EF Core则具有分叉。