1

介绍

我有一个客户端-服务器架构,其中服务器使用 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; }
}

当然,实际的实体是不共享的。

问题

程序的不同部分只需要部分数据。例如,一部分可以使用 Type 的实体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,而是通过 WCF 服务从服务器检索其数据。因此,DbSet不能在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它没有实现接口,尽管它包含了它的所有成员。我尝试了一些不同的方法,但都没有真正奏效:

尝试 1

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

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

尝试 2

我没有使用适配器类,而是尝试使用适配器接口,它派生自IDbSet必要的接口:

public ICustomDbSet<SharedType> MyEntities{ get; set; }
IEntityCache<SharedType> IEntityProvider<SharedType>.Elements { get { return MyEntities; } }

这不起作用,因为 EntityFramework 没有设置ICustomDbSet. 可能是因为它设置的值是 no IEntityCache

解决方案

在写这个问题时,我找到了一个很好的解决方案(我将作为答案发布)。那么,为什么我要发布这个问题呢?首先,我想知道,是否有任何其他看起来更合理的方法,以及我的解决方案是否有一些缺点。其次,该解决方案可能对其他人有所帮助。第三,写这个问题花了一段时间,扔掉它会很可惜:)

4

1 回答 1

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可以以从服务而不是数据库检索数据的方式实现。此外,程序的子部分不必关心他们的数据来自哪里。

于 2012-10-15T14:56:30.183 回答