我应该使用(InThreadScope或InRequestScope)配置MVC 5和Ninject工作单元吗?

时间:2015-04-02 20:57:02

标签: asp.net-mvc-5 ninject unit-of-work

我正在尝试使用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,我已经解释过它不起作用......

感谢您提出的建议,如果需要,我可以详细说明我的实施细节。

0 个答案:

没有答案