实体框架IUnitOfWorkFactory实现

时间:2017-04-17 11:59:22

标签: c# entity-framework-6 unit-of-work

我的基础架构层(SomeCompany.SomeProduct.Infrastructure)上有3个接口:

public interface IRepository<TEntity> where TEntity : Entity
{
    TEntity Insert(TEntity entity);
    // ... ther CRUD methods 
}

public interface IUnitOfWork
{
    void Commit();
    void Rollback();
}

public interface IUnitOfWorkFactory
{
    IUnitOfWork Create(Isolationlevel isolationLevel);
    IUnitOfWork Create(); // For default isolationLevel = Isolationlevel.ReadCommited
}

所以,在应用服务层(业务逻辑层)(SomeCompany.SomeProduct.BusinessLogic)中,我想做类似的事情:

public class CustomerService : ICustomerService
{
    readonly ICustomerRepository _customerRepository;
    readonly IUnitOfWorkFactory _unitOfWorkFactory;

    public CustomerService(IUnitOfWorkFactory unitOfWorkFactory, ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository;
        _unitOfWorkFactory = unitOfWorkFactory;
    }

    public void CreateCustomer(CreateCustomerRequest request)
    {
        using (var unitOfWork = _unitOfWorkFactory.Create())
        {
            try
            {
                customer = new Customer { FirstName = request.FirstName, LastName = request.LastName };
                _customerRepository.Add(customer);
                unitOfWork.Commit();
            }
            catch (Exception ex)
            {
                unitOfWork.Rollback();
            }
        }
    }
}

此代码来自https://lostechies.com/derekgreer/2015/11/01/survey-of-entity-framework-unit-of-work-patterns/

要控制DbContext有效期,我希望_unitOfWorkFactory.Create()创建一个新的DbContext

我可以这样做,但是如果我在构造函数中先前注入了存储库,那么存储库如何才能访问当前DbContext(来自创建的unitOfWork)?

我需要一个线程安全的解决方案。

请帮帮我! UoWFactory如何将dbContext共享到注入的存储库?!

_________________________________________________________________________

更新1:

这是错误的方式? -

public class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : Entity
{
    protected readonly IDbContext _dbContext;

    public RepositoryBase(IDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public virtual TEntity Insert(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentNullException("entity");

        return _dbContext.Set<TEntity>().Add(entity);
    }   

    // other methods
}

public class UnitOfWork : IUnitOfWork
{
    private readonly IDbContext _dbContext;
    private readonly IsolationLevel _isolationLevel;

    protected DbContextTransaction _transaction;

    private bool _isTransactionBeginer = false;
    private bool _commited = false;
    protected bool _disposed = false;

    public UnitOfWork(IDbContext dbContext, IsolationLevel isolationLevel)
    {
        if (dbContext == null)
            throw new ArgumentNullException("dbContext");

        _dbContext = dbContext;
        _isolationLevel = isolationLevel;

        if (_dbContext.Database.CurrentTransaction == null)
        {
            _transaction = _dbContext.Database.BeginTransaction(_isolationLevel);
            _isTransactionBeginer = true;
        }
    }

    // Dispose ...

    public void Commit()
    {
        _dbContext.SaveChanges();

        if (_isTransactionBeginer && _transaction != null)
        {
            _transaction.Commit();
            _transaction = _dbContext.Database.BeginTransaction(_isolationLevel);
            _commited = true;
        }
    }
}

public class UnitOfWorkFactory<TDbContext> : IUnitOfWorkFactory<TDbContext> where TDbContext : IDbContext
{
    private readonly TDbContext _dbContext;

    public UnitOfWorkFactory(TDbContext dbContext)
    {
        if (dbContext == null)
            throw new ArgumentNullException("dbContext");

        _dbContext = dbContext;
    }

    public IUnitOfWork Create(IsolationLevel isolationLevel)
    {
        return new UnitOfWork(_dbContext, isolationLevel);
    }

    public IUnitOfWork Create()
    {
        return Create(IsolationLevel.ReadCommitted);
    }
}

现在在服务中我有这个:

public class CustomerService  : ICustomerService
{
    private readonly IUnitOfWorkFactory<IApplicationDbContext> _uowFactory;
    private readonly ICustomerRepository _customerRepository;

    public CustomerService(IUnitOfWorkFactory<IApplicationDbContext> uowFactory, ICustomerRepository _customerRepository)
    {
        _uowFactory = uowFactory;
        _customerRepository = _customerRepository;
    }

    public void EditCustomer(int customerId, string customerName)
    {
        Customer customer = _customerRepository.FindbyId(customerId); // working with IApplicationDbContext (ApplicationDbContext) instance. Without transaction.

        customer.ChangeName(customerName);
        // some validation...

        using(var uow = _uowFactory.Create()) // use same ApplicationDbContext instance, but start new transaction if not nested uow
        {
            _customerRepository.Update(customer);
            uow.Commit(); // Transaction of ApplicationDbContext commited;
        } // Close transaction if not nested uow
    }
}

因此,最重要的部分是注册IoC容器。我正在使用Autofac:

builder.RegisterType<ApplicationDbContext>()
    .As<IApplicationDbContext>()
    .InstancePerRequest();

或者它应该是InstancePerLIfetimeScope()?它是线程安全吗?

0 个答案:

没有答案
相关问题