Nic*_*lai 3 .net c# entity-framework unity-container
我有以下代码用 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);
Run Code Online (Sandbox Code Playgroud)
我使用PerRequestLifetimeManager所以我遵循了MSDN上的建议并在上面的代码末尾添加了新行:
DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
Run Code Online (Sandbox Code Playgroud)
但是在我放置之后。当页面(仅静态 html)加载时,我将 ajax 请求发送到我的 WebApi 控制器,该控制器调用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);
}
}
Run Code Online (Sandbox Code Playgroud)
PS 我使用最新版本的Unity 3.5.1404。
提前致谢。
编辑:
Repository 的 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
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
服务GetAll()方式:
public List<Theme> GetAll(int page = 1, int pageSize = 10)
{
return UnitOfWork.ThemeRepository.Get(null, null, "Comments", page, pageSize).ToList();
}
Run Code Online (Sandbox Code Playgroud)
所以我会有这样的依赖结构:
你会坚持使用 Unity 处理每个的生命周期。问题是,您希望服务具有请求范围,就像其他服务(UoW 和 Repos)一样。您可能以这种方式设置了服务生命周期,但我对 Unity 一无所知。我可以看到您确实有 UofW 和 repos 设置了请求生命周期。
最大的区别在于它UnitOfWork不依赖于存储库,而是相反。所以存储库基类DbSet<T>通过UnitOfWork它获得它,它有DbContext.你有一些方法,UnitOfWork它会返回一个IDbSet<T>就像你在DbContext.The上调用它一样,它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
}
Run Code Online (Sandbox Code Playgroud)
TheUnitOfWork将是类似的,但将 theDbContext作为依赖项(您可能已经有了 this 但省略了构造函数):
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>();
]
}
Run Code Online (Sandbox Code Playgroud)
该服务将注入存储库:
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.
}
Run Code Online (Sandbox Code Playgroud)
该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;
}
Run Code Online (Sandbox Code Playgroud)
最终的想法是 Unity 容器处理所有依赖项的生命周期,并且UnitOfWork不必尝试管理存储库。你的线路
DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
Run Code Online (Sandbox Code Playgroud)
会留下来,DbContext由 Unity 处理,您不必Dispose()自己调用它。
尝试使用 Microsoft.Practices.Unity.HierarchicalLifetimeManager 代替,\xc2\xb4s 方式:
\n\ncontainer.RegisterType<DbContext, VotingSystemContext>(new HierarchicalLifetimeManager(), new InjectionConstructor());\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n\nMicrosoft.Practices.Unity.HierarchicalLifetimeManager 提供:
\n\n\n
\n- 每次请求后调用 Dispose()
\n- 每个请求使用相同的 DbContext 实例
\n
| 归档时间: |
|
| 查看次数: |
12465 次 |
| 最近记录: |