Здравствуйте! Я реализовал шаблон UoW / Repository в своем приложении, следуя среди прочего Учебникам MSDN.Однако я смущен, когда речь заходит об удалении контекста (что по общему признанию связано с тем фактом, что мне еще многое предстоит узнать об управлении памятью в C #).
В любом случае, у меня есть контекст, который передаетсяна:
- единица работы
- универсальные репозитории
- конкретные репозитории
Мой вопрос: когда именно мне следует распоряжаться этим контекстоми какой из моих интерфейсов должен быть производным от IDisposable / какие классы должны реализовывать IDisposable?
В настоящее время я наследую от IDisposable в IGenericRepository и IUnitOfWork, а затем реализую метод Dispose в GenericRepository и UnitOfWork.Но в руководствах по 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;
}