通用UnitOfWork和存储库

时间:2014-11-19 07:30:00

标签: c# entity-framework asp.net-web-api

我正在重构我的代码,我首先删除了服务层中对Entity Framework的引用。该层使用位于我的DAL层中的工作单元和存储库(通过接口)。

现在我遇到了一个问题,因为我的基本存储库类看起来像这样:

public interface IDatabaseFactory<C> : IDisposable
{
    C Get();
    void Set(string connectionString);
}

public abstract class Repository<C, T> : IRepository<T> 
                                         where C : DbContext, IBaseContext 
                                         where T : class, IEntity
{
    protected readonly IDbSet<T> dbset;
    private C dataContext;

    protected Repository(IDatabaseFactory<C> databaseFactory)
    {
        this.DatabaseFactory = databaseFactory;
        this.dbset = DataContext.Set<T>();
    }

    protected IDatabaseFactory<C> DatabaseFactory
    {
        get;
        private set;
    }

    protected C DataContext
    {
        get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
    }

    public virtual void Add(T entity)
    {
        dbset.Add(entity);
    }

    //etc...
}

我显然需要在类型C上使用DbContext约束。但是,如果我这样做,我会在dataContext上遇到错误,因为它无法在DbContext中解析C.

我该如何克服这个问题?

修改

典型的存储库如下所示:

public interface ICustomerTypeRepository : IRepository<CustomerType> { }

public class CustomerTypeRepository : Repository<IBaseContext, CustomerType>, ICustomerTypeRepository
{
    public CustomerTypeRepository(IDatabaseFactory<IBaseContext> databaseFactory)
        : base(databaseFactory) { }
}

在下面建议的更改之后,我仍然会遇到相同的错误:

  

类型&#39; IBaseContext&#39;不能用作类型参数&#39; TContext&#39;在通用类型或方法&#39;存储库&#39;。来自&#39; IBaseContext&#39;没有隐式参考转换。 to&#39; System.Data.Entity.DbContext&#39;。

2 个答案:

答案 0 :(得分:0)

要修复编译错误,您必须为通用类型设置适当的约束(我已将C替换为TContext以提高可读性):

interface IBaseContext { }
interface IDatabaseFactory<TContext> : IDisposable
    where TContext : DbContext
{
    TContext Get();
    void Set(string connectionString);
}

interface IEntity { }
interface IRepository<T> 
    where T : class, IEntity
{ }

abstract class Repository<TContext, T> : IRepository<T>
    where TContext : DbContext, IBaseContext
    where T : class, IEntity
{
    protected readonly IDbSet<T> dbset;
    private TContext dataContext;

    protected Repository(IDatabaseFactory<TContext> databaseFactory)
    {
        this.DatabaseFactory = databaseFactory;
        this.dbset = DataContext.Set<T>();
    }

    protected IDatabaseFactory<TContext> DatabaseFactory { get; private set; }
    protected TContext DataContext
    {
        get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
    }

    public virtual void Add(T entity)
    {
        dbset.Add(entity);
    }

    //etc...
}

但是从架构的角度来看,在存储库中持有对DbContext的引用似乎是多余的。当然,如果没有关于所有类型的知识,很难提出更好的解决方案。

答案 1 :(得分:0)

要从代码中删除DbContext,您需要更改IDatabaseFactory,如下所示:

public interface IDatabaseFactory : IDisposable
{
    T Set<T>() where T : IEntity;
}

然后您可以更改存储库

public abstract class Repository<T> : IRepository<T> 
                                     where T : class, IEntity
{
    protected readonly IDbSet<T> dbset;

    protected Repository(IDatabaseFactory databaseFactory)
    {
        this.dbset = databaseFactory.Set<T>();
    }
    // other code
}

IDatabaseFactory的实现:

public class DatabaseFactory : IDatabaseFactory
{
    private readonly DbContext _context;

    public DatabaseFactory(DbContext context)
    {
        _context = context;
    }

    public T Set<T>() where T : Entity
    {
        return _context.Set<T>();
    }
 }