UnitOfWork工厂的Repository <tentity>实现了什么?

时间:2017-03-13 20:11:19

标签: c# asp.net entity-framework

美好的一天, 我想使用来自this example的UnitOfWork(实体框架) - 存储库 - 应用服务层。 应用服务示例:

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();
      }
    }
  }
}

如何将unitOfWork Context与Repository交互?我如何在存储库(_customerRepository)中共享当前上下文(通过使用UnitOfWork工厂)?交易怎么样?

作为DI容器,它使用AutoFac。

提前致谢!

1 个答案:

答案 0 :(得分:1)

如果你想同时使用我建议你做这样的事情

public interface IUnitOfWork
{
    void Commit();
    IDbSet<T> Set<T>() where T : class;
}

现在你的DBContext实现它:

public class MyDBContext : DbContext, IUnitOfWork
{
    public void Commit()
    {
        SaveChanges();
    }

    public int SaveChanges()
    {
         //see below
        SetIsolationLevel();

        base.SaveChanges();
    }
}

对于存储库,您只需要传递DBContext

public class Repository<TEntity> : IRepository<TEntity>
    where TEntity : EntityBase
{
     protected DbContext Context;

     //this is the constructor for your base repositories
     public Repository(DbContext context)
     {
        if (context == null)
        {
            throw new ArgumentNullException();
        }

        Context = context;
    }

    public void Save(TEntity entity)
    {
        Save(entity);
    }

    public void Save(TEntity entity)
    {
        if (entity == null) return;

        if (entity.Id == 0)
        {
            Add(entity);
        }
        else
        {
            //state is modified
            Context.Entry(entity).State = EntityState.Modified;
            Context.Set<TEntity>().Attach(entity);
        }
    }

但是,您的DI应该只保存对每种类型的引用,以便在您需要时解决它们,您有责任知道您注入的类型和参数。

现在对于您的交易,根据您要指定的隔离级别,您可以执行类似这样的操作

        public MyDBContext (string connectionName)
            : base(connectionName)
        {

            Configuration.AutoDetectChangesEnabled = false;
            Configuration.LazyLoadingEnabled = false;
            Configuration.ProxyCreationEnabled = false;
            Database.CommandTimeout = 300;
            Database.Log = sql => Debug.WriteLine(sql);

            SetIsolationLevel("READ UNCOMMITTED");
        }

        private void SetIsolationLevel(string isolationLevel = null)
        {
            if (isolationLevel == null)
                isolationLevel = TransactionUtils.IsolationLevelString;

            if (!string.IsNullOrEmpty(isolationLevel))
            {
                Database.ExecuteSqlCommand($"SET TRANSACTION ISOLATION LEVEL {isolationLevel};");
            }
        }

无论如何,我强烈建议您阅读这篇文章,以便在想要使用您的工作单元和存储库时有另一种观点

http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/