![](/img/trans.png)
[英]Unity inject PerRequestLifetimeManager with background tasks?
[英]Unity DI Inject DbContext with PerRequestLifetimeManager
我有以下代码可使用Unity初始化实例:
IUnityContainer container = new UnityContainer();
container.RegisterType<DbContext, VotingSystemContext>(new PerRequestLifetimeManager(), new InjectionConstructor());
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<>));
container.RegisterType<IUnitOfWork, UnitOfWork>(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 constroller发送ajax请求,该WebApi constroller调用该类的GenericReposirory
Get()
方法, The operation cannot be completed because the DbContext has been disposed.
方法抛出错误: 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<TEntity> : IGenericRepository<TEntity> where TEntity : BaseEntity
{
public GenericRepository(VotingSystemContext context)
{
_context = context;
_dbSet = context.Set<TEntity>();
}
private readonly DbSet<TEntity> _dbSet;
private readonly VotingSystemContext _context;
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "", int? page = null, int? pageSize = null)
{
IQueryable<TEntity> query = _dbSet;
if (filter != null)
{
query = query.Where(filter);
}
List<string> 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<VotingModel> Get(int page = 1, int size = 10)
{
//get all themes
List<Theme> 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<VotingModel> model = themes.Select(t =>
{
MembershipUser membershipUser = Membership.GetUser(t.UserId ?? -1);
return t.ToVotingModel(membershipUser != null ? membershipUser.UserName : string.Empty);
}).ToList();
return model;
}
服务GetAll()
方法:
public List<Theme> GetAll(int page = 1, int pageSize = 10)
{
return UnitOfWork.ThemeRepository.Get(null, null, "Comments", page, pageSize).ToList();
}
因此,我将具有如下所示的依赖结构:
并且您会坚持使用Unity来处理每个生命周期。 事实是,您希望服务具有请求范围,就像其他服务(UoW和Repos)一样。 您可能以这种方式设置了服务寿命,但我不知道Unity是我的头等大事。 我可以看到您确实为UofW和repos设置了请求生存期。
最大的区别在于, UnitOfWork
不依赖于存储库,而是相反。 因此,存储库基类通过具有DbContext.
的UnitOfWork
获取其DbSet<T>
DbContext.
您在UnitOfWork
上有一些方法可以返回IDbSet<T>
就像在DbContext.
上调用它DbContext.
UnitOfWork
是DbContext
的包装, DbContext
本身就是类似Work of Unit的包装。
public sealed class GenericRepository<T> : IRepository<T> where T : BaseEntity
{
private readonly IDbSet<T> _dbSet;
private readonly IUoW _uoW;
public GenericRepository(IUoW unitOfWork)
{
_uoW = unitOfWork;
_dbSet = _uoW.Set<T>();
}
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "", int? page = null, int? pageSize = null)
{
IQueryable<TEntity> query = _dbSet;
if (filter != null)
{
query = query.Where(filter);
}
List<string> 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<T> Set<T>()
{
return _context.Set<T>();
]
}
该服务将注入存储库:
public class ThemeService
{
private IRepository<Theme> ThemeRepository { get; set; }
public ThemeService(IRepository<Theme> themeRepo)
{
ThemeRepository = themeRepo;
}
public List<Theme> 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<VotingModel> Get(int page = 1, int size = 10)
{
//get all themes
List<Theme> 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<VotingModel> 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<DbContext, VotingSystemContext>(new HierarchicalLifetimeManager(), 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/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.