你好,我在我的应用程序中实现了UoW/Repository模式,特别是遵循MSDN教程。但是,在处理上下文时,我很困惑(诚然,这是因为我还有很多关于 C# 内存管理的知识要学(。
无论如何,我有一个上下文传递给:
- 工作单元
- 通用存储库
- 特定存储库
我的问题:我应该在什么时候处理该上下文,以及我拥有的哪些接口应该从 IDisposable 派生/哪些类应该实现 IDisposable?
目前,我从 IGenericRepository 和 IUnitOfWork 中的 IDisposable 派生,然后在 GenericRepository 和 UnitOfWork 中实现 Dispose 方法。但是在 MSDN 教程中,Dispose 方法的实现是在特定存储库中,而不是在通用存储库中,这就是我感到困惑的原因。如果我正在使用从基类(通用存储库(传递到使用基构造函数获取上下文的特定存储库的上下文的相同实例,那么如果我在通用存储库中处理它,这还不够吗?
接口:
public interface IUnitOfWork : IDisposable
{
IAccountsRepository Accounts { get; }
ITransactionsRepository Transactions { get; }
IAccountGroupsRepository AccountGroups { get; }
void Complete();
}
public interface IGenericRepository<TEntity> : IDisposable where TEntity : class
{
void Add(TEntity entity);
void Edit(TEntity entity);
IEnumerable<TEntity> GetAll();
TEntity GetById(object id);
void Remove(object id);
void Remove(TEntity entity);
}
public interface IAccountsRepository : IGenericRepository<Account>
{
IEnumerable<Account> GetForUser(string applicationUserId);
string GetAccountName(int accountId);
}
实现:
public class UnitOfWork : IUnitOfWork
{
private readonly TinyBooksDbContext _context;
private bool _disposed;
public IAccountsRepository Accounts { get; }
public ITransactionsRepository Transactions { get; }
public IAccountGroupsRepository AccountGroups { get; set; }
public UnitOfWork(TinyBooksDbContext context)
{
_context = context;
Accounts = new AccountsRepository(_context);
Transactions = new TransactionsRepository(_context);
AccountGroups = new AccountGroupsRepository(_context);
}
public void Complete()
{
_context.SaveChanges();
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_context.Dispose();
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
private readonly TinyBooksDbContext _context;
private readonly DbSet<TEntity> _dbSet;
private bool _disposed;
public GenericRepository(TinyBooksDbContext context)
{
_context = context;
_dbSet = _context.Set<TEntity>();
}
// C
public virtual void Add(TEntity entity)
{
_dbSet.Add(entity);
}
public virtual IEnumerable<TEntity> GetAll()
{
return _dbSet.ToList();
}
// R
public virtual TEntity GetById(object id)
{
return _dbSet.Find(id);
}
// U
public virtual void Edit(TEntity entity)
{
_dbSet.Attach(entity);
_context.Entry(entity).CurrentValues.SetValues(entity);
}
// D
public virtual void Remove(object id)
{
var entity = _dbSet.Find(id);
Remove(entity);
}
public virtual void Remove(TEntity entity)
{
if (_context.Entry(entity).State == EntityState.Detached)
_dbSet.Attach(entity);
_dbSet.Remove(entity);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_context.Dispose();
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public class AccountsRepository : GenericRepository<Account>, IAccountsRepository
{
private readonly TinyBooksDbContext _context;
private bool _disposed;
public AccountsRepository(TinyBooksDbContext context) : base(context)
{
_context = context;
}
public IEnumerable<Account> GetForUser(string applicationUserId) =>
_context.Accounts.Where(a => a.ApplicationUserId == applicationUserId).ToList();
public string GetAccountName(int accountId) =>
_context.Accounts.SingleOrDefault(a => a.Id == accountId).Name;
}
一般来说,上下文的创建者应该处理它。
不要在你传入的类中释放上下文,因为这会使其他开发人员感到困惑,他们可能会在释放上下文后使用该上下文。
在您的示例中,存储库不应释放上下文 - 它们不拥有上下文。
您可以在 UnitOfWork 类中的声明期间初始化上下文,其生存期将取决于 UnitOfWork 类的生存期。
public class UnitOfWork : IDisposable, IUnitOfWork
{
private readonly TinyBooksDbContext context = new TinyBooksDbContext();
......
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_context.Dispose();
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
这样,您的上下文将与 UoW 实例一起处置。不应在通用存储库中使用释放方法。