我有以下代码用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控制器发送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);
}
}
P.S。我使用最新版本的 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();
}
答案 0 :(得分:4)
所以我会有这样的依赖结构:
并且你坚持使用Unity来处理每个人的生命。但事情是,您希望服务具有请求范围,就像其他服务(UoW和Repos)一样。您可以按照这种方式设置服务生命周期,但我并不了解Unity。我可以看到你确实拥有UofW和repos设置请求生命周期。
最大的区别在于UnitOfWork
并不依赖于存储库,而是相反。因此,存储库基类通过DbSet<T>
通过UnitOfWork
得到DbContext.
您UnitOfWork
上有一些方法可以返回IDbSet<T>
就像你在DbContext.
UnitOfWork
上调用DbContext
作为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;
}
:
UnitOfWork
最终的想法是Unity容器处理所有依赖项的生命周期,DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
不必尝试管理存储库。你的行
DbContext
将留下并且Dispose()
将被Unity处理掉,而您不必自己致电{{1}}。
答案 1 :(得分:2)
尝试使用Microsoft.Practices.Unity.HierarchicalLifetimeManager,这样:
container.RegisterType<DbContext, VotingSystemContext>(new HierarchialLifetimeManager(), new InjectionConstructor());
Microsoft.Practices.Unity.HierarchicalLifetimeManager提供:
- 每次请求后的Dispose()调用
- 每个请求使用相同的DbContext实例
醇>