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.
UnitOfWork
是DbContext
的包装器,它本身就像工作单元一样。
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提供:
- 每次请求后调用Dispose()
- 每个请求都有相同的DbContext实例
喜欢文章: https : //jasenhk.wordpress.com/2013/06/11/unit-of-work-and-repository-pattern-with-unity-dependency-injection/