1

序章

サーバーがEntityFramework5.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。おそらくそれが設定する値のために、はありません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 に答える