在使用DI和UoW模式时,我是否需要使用EF语句

时间:2017-02-06 10:11:32

标签: c# entity-framework

在许多基本示例中,我看到包含DbContext用法的使用块如下:

using (var context = new MyDbContext()) 
{     
    // Perform data access using the context 
}

这是有道理的,因为正在创建一个“新”实例,因此一旦完成它就要处理它。

使用DI

然而,在我正在使用的许多项目中,我看到DbContext被注入到存储库和服务层中,如下所示:

public class FileRequestService : IFileRequestService
{
    private readonly MyDbContext _myDbContext;

    public FileRequestService(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

    public FileRequest SaveFileRequest(FileRequest fileRequest)
    {
        fileRequest.Status = FileRequestStatus.New;
        //...
        //...
        var fr = _myDbContext.FileRequests.Add(fileRequest);
        _myDbContext.SaveChanges();
        return fr;
    }
}

并在DI容器中配置如下:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

container.Register<MyDbContext>(Lifestyle.Singleton);

问题1

这里是否没有使用using语句,因为它可能会在Web请求死亡后被处理掉?

使用DI / UoW

工作单元模式的类似场景,我看到了:

public class RecordController : Controller
{
  private readonly IUnitOfWork _unitOfWork;

  public RecordController(IUnitOfWork unitOfWork)
  {
      _unitOfWork = unitOfWork;
  }

  [HttpPost, ActionName("Index")]
  public PartialViewResult Search(SearchQueryViewModel searchQueryViewModel)
  {    
      var deptId =
      _unitOfWork.DepartmentRepository.Get(x => x.DepartmentCode == searchQueryViewModel.code)
      .Select(s => s.DepartmentId)
      .FirstOrDefault();
       //...                
   }
}

在容器中配置如下:

container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
container.Register<IGenericRepository<Department>, GenericRepository<Department>>(Lifestyle.Scoped);

正常情况下DbContext被注入到UoW类的构造函数中。

问题2

再次可以,这里没有使用using语句,或者我应该在UoW类上实现IDisposable接口并执行以下操作:

using (_unitOfWork)
{    
  var deptId =
  _unitOfWork.DepartmentRepository.Get(x => x.DepartmentCode == searchQueryViewModel.code)
  .Select(s => s.DepartmentId)
  .FirstOrDefault();
  //...
}

1 个答案:

答案 0 :(得分:2)

简单地说,创建实例的人应该是负责调用其dispose方法的人。

关于问题1: 我个人会避免在DbContext中使用单例。谷歌上的快速搜索显示了许多文章/ Stackoverflow问题,但这里是第一个问题:Entity Framework Context in Singleton 在你目前的情况下 - 它永远不会被处理掉。它在单例范围内注册,这意味着您将拥有一个与容器一样长的单个实例。 (简单的进样器范围帮助页面供参考 - http://simpleinjector.readthedocs.io/en/latest/lifetimes.html

关于问题2: 一旦离开其范围,大多数容器将调用所有IDisposable实例的dispose方法。如果您之前调用自己处置,则最终可能会将要作为依赖项提供的实例部署到其他位置。这样做会导致其他代码尝试使用同一个处理的实例...

编辑:如果范围不受DI框架控制,您必须自己调用dispose。但这不是我们正在讨论的情况