我的基础架构层(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()
?它是线程安全吗?