好的,我想出了一种方法来解决这个问题。首先,此方法实际上可以用于 Database 1st 或 Code 1st 方法,因为没有修改 Context 并且只使用了它的一个实例。
一些示例将 IUnitOfWork 接口直接应用于自动生成的AdventureWorks2008R2Entities
类。但是,您不希望这样做,因为修改可能被覆盖的自动生成代码并不是一个好主意。
这个想法是让通用存储库(或者如果不使用通用存储库,每个单独的存储库)接受 EF 上下文的实例,如下所示:
public GenericRepository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
现在 IUnitOfWork 接口应该声明 EF 的方法和每个存储库类型的实例,如下所示:
public interface IUnitOfWork : IDisposable
{
GenericRepository<Person> PersonRepository { get; }
GenericRepository<PersonPhone> PersonPhoneRepository { get; }
void Save();
}
如果尚未实例化,则该实现将新建一个存储库实例,如下所示:
公共类 UnitOfWork : IUnitOfWork { private DbContext _context; 私有 GenericRepository _personRepository;私有 GenericRepository _personPhoneRepository;
public UnitOfWork(DbContext context)
{
_context = context;
}
public GenericRepository<Person> PersonRepository
{
get
{
if (this._personRepository == null)
{
this._personRepository = new GenericRepository<Person>(_context);
}
return _personRepository;
}
}
public GenericRepository<PersonPhone> PersonPhoneRepository
{
get
{
if (this._personPhoneRepository == null)
{
this._personPhoneRepository = new GenericRepository<PersonPhone>(_context);
}
return _personPhoneRepository;
}
}
public void Save()
{
try
{
_context.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
}
}
#region Implementation of IDisposable
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes off the managed and unmanaged resources used.
/// </summary>
/// <param name="disposing"></param>
private void Dispose(bool disposing)
{
if (!disposing)
return;
if (_disposed)
return;
_disposed = true;
}
private bool _disposed;
#endregion
}
最后,要将工作单元实例用于您的存储库,您可以通过它到达适当的存储库实例,UoW 将确保所有保存的更改都发生在相同的上下文中:
_unitOfWork.PersonRepository.Insert(person);
_unitOfWork.Save();