通用工作单位

时间:2019-04-03 08:23:57

标签: c# entity-framework design-patterns repository-pattern unit-of-work

我正在尝试为数据访问层创建存储库和UnitOfWork。在当前的实现中,每次创建新存储库时,都必须修改UnitOfWork。我想避免这种情况,并保留扩展我的存储库抽象类的功能。

以下是我的通用存储库和UnitOfWork接口及类

public interface IRepositoryBase<T> where T : class
{
    IList<T> FindAll();
    T FindByCondition(Expression<Func<T, bool>> expression);
    void Create(T entity);
    void Update(T entity);
    void Delete(T entity);
}

public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
    protected DBContext _dbContext { get; set; }

    public RepositoryBase(DBContext dbContext)
    {
        _dbContext = dbContext;
    }
    //other methods removed
    public void Create(T entity)
    {
        _dbContext.Set<T>().Add(entity);
    }
}

public interface IUnitOfWork 
{
    IReminderRepository Reminder { get; }
    void Save();
}

public class UnitOfWork : IUnitOfWork, IDisposable
{
    protected DBContext _dbContext { get; set; }
    private IReminderRepository _reminderRepository;

    public UnitOfWork(DBContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IReminderRepository Reminder
    {
        get
        {
            return _reminderRepository = _reminderRepository ?? new ReminderRepository(_dbContext);
        }
    }

    public void Save()
    {
        _dbContext.SaveChanges();
    }

    public void Dispose()
    {
        _dbContext.Dispose();
    }
}

在这里,我可以通过将特定的Repository实施为以下方式来扩展我的Repository

public interface IReminderRepository : IRepositoryBase<Reminder>
{
    IList<Reminder> GetAllReminders();
    Reminder GetReminderById(Guid id);    
    Reminder GetReminderByName(string name);    
    void CreateReminder(Reminder reminder);    
    void UpdateReminder(Reminder reminder);    
    void DeleteReminder(Reminder reminder);    
}

public class ReminderRepository : RepositoryBase<Reminder>, IReminderRepository
{
    public ReminderRepository(DBContext dbContext)
    : base(dbContext)
    {
        _dbContext = dbContext;
    }
    //other methods removed
    public Reminder GetReminderByName(string name)
    {
        return FindAll()
            .OrderByDescending(r => r.Name)
            .FirstOrDefault(r => r.Name == name);

        //return FindByCondition(r => r.Name == name);
    }
}

可以,但是每当我创建一个新的特定存储库时,都必须通过为新存储库添加新属性来修改UnitOfWork类。

我在网上搜索时发现了以下内容,但由于我的RepositoryBase是一个抽象类,因此在我的情况下不起作用。

public interface IUnitOfWork 
{
    void Save();
}

public class UnitOfWork : IUnitOfWork, IDisposable
{
    private readonly DBContext _dbContext { get; set; }
    private readonly Dictionary<Type, object> _repositories = new Dictionary<Type, object>();

    public Dictionary<Type, object> Repositories
    {
        get { return _repositories; }
        set { Repositories = value; }
    }

    public UnitOfWork(DBContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IRepositoryBase<T> Repository<T>() where T : class
    {
        if (Repositories.Keys.Contains(typeof(T)))
        {
            return Repositories[typeof(T)] as IRepositoryBase<T>;
        }

        IRepositoryBase<T> repo = new RepositoryBase<T>(_dbContext);//This does not work
        Repositories.Add(typeof(T), repo);
        return repo;
    }

    public void Save()
    {
        _dbContext.SaveChanges();
    }
}

1 个答案:

答案 0 :(得分:1)

您显然需要在代码中的某个地方获得对IReminderRepository的引用,才能使用其余的特定API。

如果您不想扩展UnitOfWork类以返回IReminderRepository,则可以在实际使用特定存储库的方法中自己创建一个,例如:

using (var context = new DBContext())
{
    IUnitOfWork uow = new UnitOfWork(context);
    ReminderRepository repository = new ReminderRepository(context);
    Reminder remainder = repository.GetReminderByName("...");
    remainder.SomeProperty = "updated value..";
    uow.Save();
}

使用工作单元的唯一目的是无论如何能够在多个不同的存储库之间共享相同的上下文。在Dictionary<Type, object>中暴露UnitOfWork并不能解决任何问题,因为使用泛型的目的是为了提供编译时类型安全。