簡體   English   中英

在工作單元/存儲庫模式中處理上下文

[英]Disposing of context in the Unit Of Work / Repository pattern

你好,我在我的應用程序中實現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實例一起處理。 您不應該在常規存儲庫中有dispose方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM