推广DbContext

时间:2012-10-15 14:56:30

标签: .net entity-framework generics

简介

我有一个客户端 - 服务器架构,其中服务器使用Entity Framework 5.0将其数据存储在不同的数据库中。因此,它具有不同的DbContext类。但是,它们之间共享一些实体类型。所以我们可以:

public class MyFirstDataAccess : DbContext
{
    //constructor omitted
    public DbSet<SharedType> MyEntities { get; set; }
    public DbSet<OtherType> MyOtherEntities { get; set; }
}
public class MySecondDataAccess : DbContext
{
    public DbSet<SharedType> MyEntitiesWithSharedType { get; set; }
}

当然,实际的实体不会被共享。

问题

程序的不同部分只需要部分数据。例如。一部分可以使用SharedType类型的实体。所以我创建了一个提供数据的通用接口:

public interface IEntityProvider<TEntity> where TEntity : class
{
    DbSet<TEntity> Elements { get; set; }

    void Dispose();
    int SaveChanges();
}

DbContext中实施界面我添加了Elements属性,该属性将替换为MyEntitiesWithSharedType DbSet<SharedType> IEntityProvider<SharedType>.Elements { get; set; } 属性:

DbContext

这实际上有效。只要提供所需的数据,程序的不同部分现在可以与任何DbContext一起使用。

我想在客户端重用服务器的某些部分。当然,客户端没有DbSet,但是通过服务器的WCF服务检索其数据。因此,IEntityProvider不能在DbSet's接口中使用,因为必须与客户端共享此接口。所以我创建了另一个接口,其中包含我需要的public interface IEntityCache<TEntity> : IEnumerable<TEntity>, IQueryable<TEntity> { ObservableCollection<TEntity> Local { get; } TEntity Add(TEntity entity); TEntity Remove(TEntity entity); } 成员:

DbSet

问题是将IEntityCache作为DbSet。它不能直接转换,因为DbSet没有实现接口,尽管它包含所有成员。我尝试了一些不同的方法,但都没有真正奏效:

尝试1

创建DbSet的子类,实现所需的接口( - &gt;类适配器)。

这不起作用,因为IDbSet没有任何公共或受保护的构造函数。因此,适配器类无效。

尝试2

我没有使用适配器类,而是尝试使用适配器接口,该接口派生自public ICustomDbSet<SharedType> MyEntities{ get; set; } IEntityCache<SharedType> IEntityProvider<SharedType>.Elements { get { return MyEntities; } } 和必要的接口:

ICustomDbSet

这不起作用,因为EntityFramework未设置IEntityCache。可能因为它设置的值不是{{1}}。

解决方案

在写这个问题时,我发现了一个非常好的解决方案(我将作为答案发布)。那么为什么我发布这个问题呢?首先,我想知道,如果有任何其他方法似乎更合理,如果我的解决方案有一些缺点。其次,解决方案可能会帮助其他人。第三,写这个问题需要一段时间,把它扔掉会很遗憾:)

1 个答案:

答案 0 :(得分:0)

我的解决方案是类适配器方法的后续步骤:使用对象适配器:

public class DbSetAdapter<TEntity> : IEntityCache<TEntity> where TEntity : class
{
    DbSet<TEntity> dbSet;

    public DbSetAdapter(DbSet<TEntity> dbSet)
    {
        this.dbSet = dbSet;
    }

    public ObservableCollection<TEntity> Local
    {
        get { return dbSet.Local; }
    }

    public TEntity Add(TEntity entity)
    {
        return dbSet.Add(entity);
    }

    public TEntity Remove(TEntity entity)
    {
        return dbSet.Remove(entity);
    }

    public IEnumerator<TEntity> GetEnumerator()
    {
        return ((IEnumerable<TEntity>)dbSet).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable)dbSet).GetEnumerator();
    }

    public Type ElementType
    {
        get { return ((IQueryable<TEntity>)dbSet).ElementType; }
    }

    public Expression Expression
    {
        get { return ((IQueryable<TEntity>)dbSet).Expression; }
    }

    public IQueryProvider Provider
    {
        get { return ((IQueryable<TEntity>)dbSet).Provider; }
    }
}

我在DbContext中使用了此适配器,如下所示:

DbSetAdapter<SharedType> entityAdapter;
...
public DbSet<SharedType> MyEntities{ get; set; }
IEntityCache<SharedType> IEntityProvider<SharedType>.Elements { 
    get 
    {
        if (entityAdapter == null)
            entityAdapter = new DbSetAdapter<SharedType>(MyEntities);
        return entityAdapter; 
    }
}

这样,IEntityCache可以以从服务而不是数据库中检索数据的方式实现。此外,该计划的子部分不必关心其数据来自何处。