Unity DI使用PerRequestLifetimeManager注入DbContext

我有以下代码用Unity初始化实例:

IUnityContainer container = new UnityContainer(); container.RegisterType(new PerRequestLifetimeManager(), new InjectionConstructor()); container.RegisterType(typeof(IGenericRepository), typeof(GenericRepository)); container.RegisterType(new PerRequestLifetimeManager()); container.RegisterTypes( AllClasses.FromAssemblies( Assembly.GetAssembly(typeof(IUserService)), Assembly.GetAssembly(typeof(UserService))), WithMappings.FromMatchingInterface, WithName.Default, WithLifetime.PerResolve); DependencyResolver.SetResolver(new Unity.Mvc4.UnityDependencyResolver(container)); GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); 

我使用PerRequestLifetimeManager所以我按照MSDN上的建议,并在上面代码的末尾添加了新行:

 DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule)); 

但在我放置之后。 当加载页面(仅静态html)时,我向我的WebApi控制器发送ajax请求,该控制器调用抛出错误的GenericReposirory Get()方法: The operation cannot be completed because the DbContext has been disposed.
没有这行代码,一切正常,但没有设置它可能不会处置上下文。
我的UnitOfWork类:

 public class UnitOfWork : IUnitOfWork, IDisposable { private readonly VotingSystemContext _context; private bool _disposed; //GenericRepository properties private void Dispose(bool disposing) { if (!_disposed) { if (disposing) { _context.Dispose(); } } _disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } 

PS我使用最新版本的Unity 3.5.1404
提前致谢。

编辑:

存储库的Get()方法:

 public sealed class GenericRepository : IGenericRepository where TEntity : BaseEntity { public GenericRepository(VotingSystemContext context) { _context = context; _dbSet = context.Set(); } private readonly DbSet _dbSet; private readonly VotingSystemContext _context; public IEnumerable Get(Expression<Func> filter = null, Func<IQueryable, IOrderedQueryable> orderBy = null, string includeProperties = "", int? page = null, int? pageSize = null) { IQueryable query = _dbSet; if (filter != null) { query = query.Where(filter); } List properties = includeProperties.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); properties.ForEach(property => { query = query.Include(property); }); if (orderBy != null) { query = orderBy(query); } if (page != null && pageSize != null) { query = query.Skip((page.Value - 1) * pageSize.Value).Take(pageSize.Value); } return query; } // other methods like Delete, Update and GetById } } 

ApiController的Get()方法:

 public IEnumerable Get(int page = 1, int size = 10) { //get all themes List themes = _themeService.GetAll(page, size); //convert themes to VotingModel (same model as Theme just without converting system throw an error about serializing object and also add new filed UserName). List model = themes.Select(t => { MembershipUser membershipUser = Membership.GetUser(t.UserId ?? -1); return t.ToVotingModel(membershipUser != null ? membershipUser.UserName : string.Empty); }).ToList(); return model; } 

Service GetAll()方法:

 public List GetAll(int page = 1, int pageSize = 10) { return UnitOfWork.ThemeRepository.Get(null, null, "Comments", page, pageSize).ToList(); } 

所以我会有这样的依赖结构:

  • UnitOfWork – 获取DbContext
  • 存储库 – 获取UnitofWork
  • 服务 – 获取存储库(ies)
  • ApiController – 获得服务

你会坚持使用Unity来处理每个人的生命。 但事情是,您希望服务具有请求范围,就像其他服务(UoW和Repos)一样。 你可能会以这种方式设置服务生命周期,但我不知道Unity是不是最重要的。 我可以看到你确实拥有UofW和repos设置请求生命周期。

最大的区别在于UnitOfWork不依赖于存储库,而是相反。 因此,存储库基类通过具有DbContext.UnitOfWork获取其DbSet DbContext. 你在UnitOfWork上有一些方法会返回一个IDbSet就像你在DbContext.上调用它DbContext. UnitOfWorkDbContext的包装器,它本身就像工作单元一样。

 public sealed class GenericRepository : IRepository where T : BaseEntity { private readonly IDbSet _dbSet; private readonly IUoW _uoW; public GenericRepository(IUoW unitOfWork) { _uoW = unitOfWork; _dbSet = _uoW.Set(); } public IEnumerable Get(Expression> filter = null, Func, IOrderedQueryable> orderBy = null, string includeProperties = "", int? page = null, int? pageSize = null) { IQueryable query = _dbSet; if (filter != null) { query = query.Where(filter); } List properties = includeProperties.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); properties.ForEach(property => { query = query.Include(property); }); if (orderBy != null) { query = orderBy(query); } if (page != null && pageSize != null) { query = query.Skip((page.Value - 1) * pageSize.Value).Take(pageSize.Value); } return query; } // other methods like Delete, Update and GetById } 

UnitOfWork类似,但将DbContext作为依赖项(您可能已经有了这个但省略了构造函数):

 public class UnitOfWork : IUnitOfWork { private readonly VotingSystemContext _context; private bool _disposed; public UnitOfWork(DbContext context) { _context = context; } public IDbSet Set() { return _context.Set(); ] } 

该服务将注入存储库:

 public class ThemeService { private IRepository ThemeRepository { get; set; } public ThemeService(IRepository themeRepo) { ThemeRepository = themeRepo; } public List GetAll(int page = 1, int pageSize = 10) { return ThemeRepository.Get(null, null, "Comments", page, pageSize).ToList(); } // etc. } 

ApiController将获得注入所需的服务,在本例中为ThemeService

 public class ApiController ThemeController { private ThemeService _themeService; public ThemeController(ThemeService service) // along with any other needed services { _themeService = service; } public IEnumerable Get(int page = 1, int size = 10) { //get all themes List themes = _themeService.GetAll(page, size); //convert themes to VotingModel (same model as Theme just without converting system throw an error about serializing object and also add new filed UserName). List model = themes.Select(t => { MembershipUser membershipUser = Membership.GetUser(t.UserId ?? -1); return t.ToVotingModel(membershipUser != null ? membershipUser.UserName : string.Empty); }).ToList(); return model; } 

最终的想法是Unity容器处理所有依赖项的生命周期,而UnitOfWork不必尝试管理存储库。 你的路线

 DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule)); 

将留下并且DbContext将被Unity处理掉,你不必自己调用Dispose()

尝试使用Microsoft.Practices.Unity.HierarchicalLifetimeManager,这样:

 container.RegisterType(new HierarchialLifetimeManager(), new InjectionConstructor()); 

Microsoft.Practices.Unity.HierarchicalLifetimeManager提供:

  1. 每次请求后调用Dispose()
  2. 每个请求都有相同的DbContext实例

喜欢文章: https : //jasenhk.wordpress.com/2013/06/11/unit-of-work-and-repository-pattern-with-unity-dependency-injection/