繁体   English   中英

使用工作单元在同一事务中从不同的存储库调用不同的方法

[英]Call different methods, from different repositories, in same transaction using Unit of work

我仍在学习 UnitOfWork 模式,对此我还不满意。 我找到了很多例子,但对于我的问题,没有什么是足够清楚的。 我想在 Ado.Net 中使用 UnitOfWork。 我有很多存储库。 我想使用工作单元在同一事务中从不同的存储库调用不同的方法。

例如,有这 2 个存储库。

public class FirstRepository : IFirstRepository
    {
        private readonly ILogger logger;
        private readonly IImportConfiguration configuration;

        public FirstRepository(ILogger logger, IImportConfiguration configuration)
        {
            this.logger = logger;
            this.configuration = configuration;
        }   
        public int Save()
        {
            //Save to DB with Ado.Net
            return 1;
        }
    }

public class SecondRepository : ISecondRepository
    {
        private readonly ILogger logger;
        private readonly IImportConfiguration configuration;

        public SecondRepository(ILogger logger, IImportConfiguration configuration)
        {
            this.logger = logger;
            this.configuration = configuration;
        }

        public int Update()
        {
            //Update in DB with Ado.Net
            return 1;
        }
    }

我想在同一个事务中调用函数 Save() 和 Update()。

using (var uow = UnitOfWorkFactory.Create())
{
     firstRepository.Save(); 
     secondRepository.Update();

     _unitOfWork.SaveChanges();
}

问题是如何在两个存储库中使用相同的 UnitOfWork ? 我唯一能看到的是向函数添加附加参数

//in first repository
Save(IUnitOfWork uow)

//in second repository
Update(IUnitOfWork uow)
//****************************
using (var uow = UnitOfWorkFactory.Create())
{
     firstRepository.Save(uow); 
     secondRepository.Update(uow);

     _unitOfWork.SaveChanges();
}

这是一个丑陋的解决方案,因为我必须在所有与 DB 一起工作的函数中都有这个参数。 我正在使用依赖注入。 ILogger 和 IImportConfiguration 注入了 AutoFac。 也许在 UnitOfWork 中注册所有存储库会很好? 但是怎么做呢? 我不能在所有存储库中只注入一个实例。 任何的想法?

public class UnitOfWork
{
    public DbSet<Company> Companies { get; set; }

    public int SaveChanges()
    {
        underlyingContext.SaveChanges();
    }
}

public class UnitOfWorkFactory
{
    public UnitOfWork Create() 
    {
        // real creation logic
        return new UnitOfWork();
    }
}

public class CompanyRepository
{
    private readonly UnitOfWork uow;

    public CompanyRepository(UnitOfWork uow)
    {
        uow = uow;
    }

    public void Add(Company company)
    {
        uow.Companies.Add(company);
    }  
}

public class CompanyRepositoryFactory
{
    public Create(UnitOfWork uow)
    {
        new CompanyRepository(uow);
    }
}

将所有内容捆绑在一起:

var uow = new UnitOfWorkFactory().Create();
var companyRepository = new CompanyRepositoryFactory().Create(uow);

因此,要使用 DI,您需要为所有这些创建接口。

工作单元基于一些数据层连接,例如 EF 使用DbContext ,您将在底层UnitOfWork类中使用它。

您可以做的其他事情是使IUnitOfWork (接口)继承IDisposable以便您使用using()

为了让你没有一百个存储库类(虽然不是一件坏事),你可以使它成为通用的,所以IRepository<T>Repository<T>

因此,对于使用 EF 的通用存储库和工作单元。

public class UnitOfWork : IUnitOfWork
{
    ProjectDbContext context;

    public UnitOfWork() {
        context = new ProjectDbContext();    
    }

    public IQueryable<T> Query<T>(Expression<Func<bool, t>> predicate)
    {
        return context.Set<T>().Where(predicate);
    }

    public void Add<T>(T entity)
    {
        context.Set<T>().Add(entity);
    }

    public int SaveChanges()
    {
        return context.SaveChanges();
    }

    public void Dispose()
    {
        context.Dispose();
    }
}

public class UnitOfWorkFactory
{
    Lazy<UnitOfWork> lazyUOW = new Lazy<UnitOfWork>(() => new UnitOfWork());

    public UnitOfWork Create() 
    {
        // having the DI initialise as Singleton isn't enough.
        return lazyUOW.Value;
    }
}

public class Repository<T> : IRepository<T>
{
    private readonly IUnitOfWork uow;

    public Repository(IUnitOfWork uow)
    {
        uow = uow;
    }

    public void Add(T entity)
    {
        uow.Add(entity);
    }

    public List<T> AllBySomePredicate(Expression<Func<bool, T>> predicate)
    {
        return uow.Query(predicate).ToList();
    }  
}

public class RepositoryFactory : IRepositoryFactory 
{
    public Create<T>(UnitOfWork uow)
    {
        new Repistory<T>(uow);
    }
}

用法:

public class CompanyController : Controller
{
     private readonly IUnitOfWorkFactory uowFactory;
     private readonly IRepositoryFactory repoFactory;

     public CompanyController (
             IUnitOfWorkFactory uowFactory,
             IRepositoryFactory repoFactory)
     {
          uowFactory = uowFactory;
          repoFactory = repoFactory;
     }

     public ActionResult Index()
     {
         using(var uow = uowFactory.Create()) 
         {
             var companyRepo = repoFactory.Create<Company>(uow);

             return View(companyRepo.AllBySomePredicate(x => x.CompanyJoined == DateTime.Now.AddMonths(-2)));
         }
     }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM