我正在开发一个WindowsForms应用程序。我正在使用Repository,UoW,DI和EntityFramework。此类应用程序中的最佳实践是每个窗体使用一个DbContext窗体。
我的问题是,当我解析表单IoC时,表单会注入我的业务服务。这应该默认创建一个新的DbContext实例,这很好。当我从同一表单打开一个子表单时,即使有新的业务服务注入到这个子表单中,也会使用相同的DbContext实例。
即使我打开一个新表单,也会使用相同的DbContext实例,除非我发布已解析的表单。
不应该是每当我解析一个组件,并且该组件有多个依赖项时,就会创建所有新实例,特别是因为我使用的是Transient生活方式。
下面是我使用的代码的简短实现。我已经包含了重要的部分。
的UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
private DbContextBase context = null;
/// <summary>
/// Constructer
/// </summary>
public UnitOfWork(DbContextBase context)
{
this.context = context;
}
/// <summary>
/// Gets current context.
/// </summary>
public DbContextBase UoWContext
{
get { return context; }
}
}
UnitOfWorkManager:
public class UnitOfWorkManager
{
private static IUnitOfWork _unitOfWork { set; get; }
private UnitOfWorkManager()
{
}
public static IUnitOfWork Current
{
get
{
if (_unitOfWork != null)
return _unitOfWork;
else
{
_unitOfWork = Create();
return _unitOfWork;
}
}
set
{
_unitOfWork = value;
}
}
private static IUnitOfWork Create()
{
return IoCManager.IoC.Resolve<IUnitOfWork>();
}
}
存储库:
public class Repository<TEntity, TKey> : IRepository<TEntity, TKey>
where TEntity : class
{
public Repository()
{
}
private DbContextBase Context
{
get
{
return UnitOfWorkManager.Current.UoWContext;
}
}
private DbSet<TEntity> DbSet
{
get
{
return Context.Set<TEntity>();
}
}
}
商业服务:
{
public class BusinessService<TEntity, TKey> : IBusinessService<TEntity, TKey>
where TEntity : IEntity
{
protected IRepository<TEntity, TKey> _repository;
public BusinessService(IRepository<TEntity, TKey> repository)
{
_repository = repository;
}
}
使用Castle-Windsor进行DI注册:
IoCManager.IoC.Register<DbContextBase, PMDbContext>(IoCLifeStyle.Transient);
IoCManager.IoC.Register<IEFUnitOfWork, EFUnitOfWork>(IoCLifeStyle.Transient);
IoCManager.IoC.Register<IRepository>(typeof(IRepository).Assembly, IoCLifeStyle.Transient);
IoCManager.IoC.Register<BusinessServiceInterceptor>(IoCLifeStyle.Singelton);
IoCManager.IoC.Register<IBusinessService, BusinessServiceInterceptor>(typeof(IBusinessService).Assembly, IoCLifeStyle.Transient, typeof(BusinessServiceInterceptor));
//Forms
IoCManager.IoC.Register<frm_Main>(PM.Common.Enums.IoCLifeStyle.Transient);
IoCManager.IoC.Register<frm_Calander>(PM.Common.Enums.IoCLifeStyle.Transient);
IoCManager.IoC.Register<frm_Calanders>(PM.Common.Enums.IoCLifeStyle.Transient);
答案 0 :(得分:0)
你必须稍微改变你的设计:
public class Repository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity : class
{
private readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
private DbContextBase Context
{
get
{
return _unitOfWork.UoWContext;
}
}
private DbSet<TEntity> DbSet
{
get
{
return Context.Set<TEntity>();
}
}
}
然后每当要求新表格时
在同一表单中对服务的每次调用都将导致调用相同的底层服务 - &gt;存储库 - &gt; unitOfWork - &gt;上下文。
如果您在表单中有更多服务,应该共享相同的uow实例:
Container.Register(Component.For<IUnitOfWork>()
.ImplementedBy<UnitOfWork>()
.LifestyleBoundToNearest<frmBase>());
(https://github.com/castleproject/Windsor/blob/master/docs/lifestyles.md)
然后uow及其上下文仅限于最近的形式。