我正在尝试使用Ninject DI框架实现工作单元。我想我已经在某种程度上做到了,但我不相信这个解决方案没有错。
我正在使用通用存储库
public class RepositoryBase<TEntity> : IRepositoryBase<TEntity> where TEntity : class
{
这是我的工作单位
public class UnitOfWork : IUnitOfWork
{
private readonly …..Context _context;
private readonly IDbTransaction _transaction;
private readonly ObjectContext _objectContext;
/// <summary>
/// Constructor
/// </summary>
public UnitOfWork(….Context context)
{
_context = context;
_objectContext = ((IObjectContextAdapter)_context).ObjectContext;
if (_objectContext.Connection.State != ConnectionState.Open)
{
_objectContext.Connection.Open();
_transaction = _objectContext.Connection.BeginTransaction();
}
}
public void SaveChanges()
{
_context.SaveChanges();
}
public void Commit()
{
_context.SaveChanges();
_transaction.Commit();
}
public void Rollback()
{
_transaction.Rollback();
foreach (var entry in _context.ChangeTracker.Entries())
{
switch (entry.State)
{
case EntityState.Modified:
entry.State = EntityState.Unchanged;
break;
case EntityState.Added:
entry.State = EntityState.Detached;
break;
case EntityState.Deleted:
// Note - problem with deleted entities:
// When an entity is deleted its relationships to other entities are severed.
// This includes setting FKs to null for nullable FKs or marking the FKs as conceptually null (don’t ask!)
// if the FK property is not nullable. You’ll need to reset the FK property values to
// the values that they had previously in order to re-form the relationships.
// This may include FK properties in other entities for relationships where the
// deleted entity is the principal of the relationship–e.g. has the PK
// rather than the FK. I know this is a pain–it would be great if it could be made easier in the future, but for now it is what it is.
entry.State = EntityState.Unchanged;
break;
}
}
}
public void Dispose()
{
if (_objectContext.Connection.State == ConnectionState.Open)
{
_objectContext.Connection.Close();
}
}
}
这与MVC论坛项目(http://www.mvcforum.com/)
中使用的工作类相同现在我正在尝试使用该模式使用该模式在我的某个服务中保存数据。
public class PermissionService : IPermissionService
{
private readonly IRepositoryBase<PermissionEntity> _repository;
private readonly ICommonRepository _commonRepository;
private readonly IUnitOfWorkManager UnitOfWorkManager;
public PermissionService(IRepositoryBase<PermissionEntity> repository, ICommonRepository commonRepository, IUnitOfWorkManager unitOfWorkManager)
{
_repository = repository;
_commonRepository = commonRepository;
UnitOfWorkManager = unitOfWorkManager;
}
...
public void AddNewPermission(PermissionEntity permission)
{
using (var unitOfWork = UnitOfWorkManager.NewUnitOfWork())
{
try
{
_repository.Add(permission);
unitOfWork.Commit();
}
catch (Exception ex)
{
unitOfWork.Rollback();
}
}
}
如果我使用InRequestScope参数绑定db上下文接口,那将无效
kernel.Bind<I….DBContext>().To<….DbContext>(). InRequestScope
当我尝试使用该模式保存数据时,如果我指定
我添加了db上下文的唯一ID属性,并且播放unitOfWork变量和_repository变量所拥有的上下文具有不同的唯一ID。因此,当我们提交另一个上下文实例时,向存储库添加元素时不会更改数据。
我是如何通过在绑定DBContext时指定.InThreadScope()
来解决的。现在我在using部分中有一个相同的db上下文,并且提交数据将数据保存到存储库中。
然后在我调试系统的另一部分时使用InThreadScope
设置,我得到一个例外:
由于已经处理了DbContext,因此无法完成操作。
public UsersEntity GetUserByUserName(string userName)
Line 34: {
Line 35: return _commonRepository.CommonDbContext.Users.FirstOrDefault(x => x.UserName == userName);
Line 36: }
Line 37:
这里我访问的是DBContext但不是使用UnitOfWork,而是直接使用我的commonRepository直接公开DBContext实例。
我无法重构所有代码以使用工作单元,因此我需要运行该代码。
一种可能的快速而肮脏的解决方案是在构造函数
中public CommonRepository(I….DbContext dbContext)
{
_commonDbContext = dbContext;
}
检查上下文是否为null并创建一个新上下文。
你觉得我走在正确的轨道上怎么样?看了很多帖子,我从来没有找到一个帖子建议使用InThreadScope()
选项进行MVC应用而不是InRequestScope
,我已经解释过它不起作用......
感谢您提出的建议,如果需要,我可以详细说明我的实施细节。