12

コードファーストアプローチでEntityFramework5を使用しており、エンティティ構成にFluentAPIを使用しています。私のプロジェクトには、データベースからデータの半分を取得し、WCFクライアント(製品在庫の管理に使用されるサードパーティシステム)を介して取得したデータコントラクトから残りの半分を取得する特定の製品エンティティがあります。データコントラクトは、Product Entityクラスのメンバーです(プロパティまたはメソッドはまだ決定していません)。

エンティティ内にWCFクライアントロジックを含めたくない。このロジックをリポジトリコード(DbContext、DbSetなど)に保持したいと思います。

では、Product Entityがデータベースから取得された直後にEntityFrameworkにフックする(またはインターセプトする)手法はありますか?製品エンティティは他のエンティティのナビゲーションプロパティとして表示されることに注意してください。フックまたはインターセプトが可能である場合、それは、EFがデータベースから製品エンティティをロードした直後にSOAPサービスからデータコントラクトを取得できることを意味します。私のプロジェクトの利点は、アプリケーション全体でWCFクライアント取得コードを繰り返す必要がないことです。

私が持っていたアイデアの1つは、データコントラクトにIDbSetを実装することであり、IDbSetがそれを取得する責任があります。そして、どういうわけかEFをだまして、ProductEntityのナビゲーションプロパティを考えさせます。しかし、データベースのDbSetをデータベース以外のIDbSetとすべて同じDbContext内で混在させることができるかどうかはわかりませんでした。また、他の質問-EFはIDbSet埋め込みからナビゲーションプロパティを取得することをどのように知るのでしょうか?時間をかける前に、このアイデアが可能かどうかを知りたいと思います。また、どこから探し始めるかを知りたいです。

私は.NETを10年以上使用していますが、このEF5のものはまだ比較的新しいものであることに注意してください。

前もって感謝します。

-サム

4

2 に答える 2

20

今日、私が探しているものと思われるイベントをEntityFrameworkで見つけました。ObjectContext.ObjectMaterializedイベント。どうやら、DbContextはIObjectContextAdapterを実装し、IObjectContextAdapterはObjectContextを公開します。そこから、ObjectMaterializedイベントをサブスクライブできます。

MSDN読み取り:クエリまたはロード操作の一部として、データソース内のデータから新しいエンティティオブジェクトが作成されたときに発生します。

次のコードは、ObjectMaterializedイベントを使用して、WCFクライアントアクセスロジックを配置するための中心点を持つことが私の好みの1つであるという問題を解決する方法を示しています。

// seperate assembly - does not use Domain.Repositories assembly
namespace Domain.Models
{
    // the data contract
    [DataContract]
    public class ProductInventoryState
    {
        [DataMember]
        public int StockStatus { get; set; }

        [DataMember]
        public IEnumerable<String> SerialNumbers { get; set; }

        // etc....
    }

    // the entity
    public class Product
    {
        public Guid Key { get; set; }
        public string ProductCode { get; set; }
        public ProductInventoryState InventoryState { get; set; }
        // etc....
    }
}

// seperate assembly - uses Domain.Models assembly
namespace Domain.Repositories
{
    public class MainRepository : DbContext
    {
        public MainRepository()
        {
            ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += ObjectContext_ObjectMaterialized;
        }

        protected void ObjectContext_ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
        {
            if (e.Entity == null)
                return;

            if (e.Entity is Product)
            {
                Product product = (Product)e.Entity;

                // retrieve ProductInventoryState from 3rd party SOAP API
                using (ThirdPartyInventorySystemClient client = new ThirdPartyInventorySystemClient())
                {
                    // use ProductCode to retrieve the data contract
                    product.InventoryState = client.GetInventoryState(product.ProductCode);
                }
            }
        }    
    }
}
于 2013-02-07T00:06:33.200 に答える
1

1.)独自のEFプロバイダーを作成できます(ただし、これは簡単な作業ではありません)

2.)アイテムをコンテキストに添付することはできますが、保存することはできません。

entity.Stateは、アタッチ後に変更なしとして設定できます。変更を保存する前に、そのようなエントリをコンテキストから削除することもできます

3)EFとロケーション2をチェックし、結果を組み合わせるリポジトリファサードを作成できます。

ナビゲーションプロパティの質問について。問題を回避するために、これらを慎重に指定する必要があります。遅延ロードされていないか、モデル化されていません。

私はそれらを個人的に混ぜようとはしません。
一部のプロパティを無視するようにEFに指示できます。したがって、NiceのオリジナルのPOCOを持つことができますが、DB上にあるビットのみをモデル化します。

その後、POCOは残りを収集します。

私は自分でイベントのあるファサードを使用して、コンテキスト/DBsetのKEYメソッドを操作します。したがって、attach、get、saveなどでイベントをトリガーできます。

幸運を

于 2013-02-05T17:10:34.943 に答える