使用工作单元在同一事务中从不同的存储库调用不同的方法
Call different methods, from different repositories, in same transaction using Unit of work
我仍在学习 UnitOfWork 模式,对此我还不太适应。我找到了很多例子,但对我的问题来说还不够清楚。
我想将 UnitOfWork 与 Ado.Net 一起使用。
我有很多存储库。我想使用工作单元从同一事务中的不同存储库调用不同的方法。
例如有这 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
class.
中使用它
您可以做的其他事情是让 IUnitOfWork
(接口)继承 IDisposable
,这样您就可以使用 using()
.
为了使您没有一百个存储库 classes(虽然这并不是一件坏事),您可以将其设为通用,因此 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)));
}
}
}
我仍在学习 UnitOfWork 模式,对此我还不太适应。我找到了很多例子,但对我的问题来说还不够清楚。 我想将 UnitOfWork 与 Ado.Net 一起使用。 我有很多存储库。我想使用工作单元从同一事务中的不同存储库调用不同的方法。
例如有这 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
class.
您可以做的其他事情是让 IUnitOfWork
(接口)继承 IDisposable
,这样您就可以使用 using()
.
为了使您没有一百个存储库 classes(虽然这并不是一件坏事),您可以将其设为通用,因此 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)));
}
}
}