Entity Framework POCO の分散キャッシュによる遅延読み込みの使用

Entity Framework は、Microsoft が提供する非常に人気のあるオブジェクト リレーショナル マッピング エンジンであり、高トラフィック アプリケーションでの使用が増えています。 また、これらの高トラフィック アプリケーションの多くは、メモリ内分散キャッシュを使用することで得られるスケーラビリティを必要とします。 ただし、状況によっては、Entity Framework とメモリ内分散キャッシュに互換性がなくなることがあります。 その方法を説明しましょう。

Entity Framework を Plain Old CLR Objects (POCO) とその遅延読み込み機能とともに使用している場合、Entity Framework は遅延読み込みを実行するためのコードを含むプロキシ オブジェクトを動的に生成します。 また、これらの動的オブジェクト定義はアプリケーション プロセス内にのみ存在するため、プロセス外の分散キャッシュ用にシリアル化することはできません。

以下は、プロキシが生成される例です。 Customer Entity Framework の遅延読み込みを使用して関連するエンティティ orders。 動的に生成されたクラス名がどのように表示されるかを確認してください。 このクラス名はアプリケーション プロセス内でのみ使用可能であり、プロセス外では不明です。

Entity Framework POCO の使用
Entity Frameworkの遅延読み込みによって生成されるプロキシの例

ここで問題となるのは、分散キャッシュは常にプロセス外であり、キャッシュする前にすべてのオブジェクトをシリアル化する必要があり、これらのオブジェクトが別のクライアント ボックスからアクセスされるときに、別のマシン上でシリアル化解除する必要がある場合があることです。 したがって、逆シリアル化のために両方のマシンでオブジェクト タイプを知っている必要があります。 また、Entity Framework で動的に生成されたプロキシでは、プロキシは XNUMX 台のマシン上のアプリケーション プロセス内でのみ認識されるため、これは不可能です。 したがって、分散キャッシュで使用するために Entity Framework でのプロキシ生成を無効にする唯一の方法がありますが、これは Entity Framework の遅延読み込み機能も侵害するため、あまり現実的なシナリオではありません。

プロキシなしで Entity Framework POCO 遅延読み込みを使用する方法は?

この問題を解決し、遅延読み込みで Entity Framework を使用するには、まずプロキシを無効にして、シリアル化の問題が発生しないようにする必要があります。 プロキシがオフになっている場合、Entity Framework では遅延読み込みがサポートされないため、アプリケーションに追加のコードを挿入して遅延読み込みを実現する必要があります。

また、この追加コードは、Entity Framework の遅延読み込み機能の実現に役立ち、同時にエンティティの POCO らしさを侵害しないように作成する必要があります。 例を挙げて、このアプローチを段階的に詳しく説明します。

あなたが持っている場合 Customer を持つオブジェクト Orders リストをプロパティとして含めると、関連するファイルにアクセスすると、遅延読み込みが機能するはずです。 Orders Customer の場合、それらはまだ読み込まれていません (つまり、Entity Framework コンテキストに存在しません)。 Customer オブジェクトは自動的に呼び出しを行い、関連するデータをロードします。 Orders。以下の例を使用して、プロキシを使用せずに Entity Framework の遅延読み込みを実装し、分散キャッシュでも使用する方法を示します。

  1. 最初のステップは、Entity Framework プロキシ生成をオフにし、Entity Framework の遅延読み込み機能もオフにすることです。 次のステップでは、遅延読み込みコードを自分で実装します。   context.ContextOptions.ProxyCreationEnabled プロパティはデフォルトで true です。 この機能をオフにするには、コンテキスト オブジェクトのデフォルト コンストラクターで明示的に「false」に設定する必要があります。
    {
      public NorthwindContext() : base("name=NorthwindContext")
      {
        this.ContextOptions.ProxyCreationEnabled = false;
        this.ContextOptions.LazyLoadingEnabled = false;
      }
    }
    プロキシ生成と Entity Framework の遅延読み込み設定を無効にすると、動的プロキシが作成されなくなり、分散キャッシュでシリアル化の問題が発生しなくなります。 実際の単純な古い CLR オブジェクト (POCO) Customer オブジェクトは Entity Framework によって使用されるため、問題なく分散キャッシュにキャッシュおよび取得できます。

  2. 次のステップでは、顧客の関連注文に対する Entity Framework の遅延読み込みを実現するのに役立つコードを導入します。 上で述べたように、このコードは目的の達成に役立ちますが、実際の顧客オブジェクトと注文オブジェクトが依然として Plain Old CLR Object (POCO) のままであることも確認する必要があります。

    このために、静的なエンティティ フレームワークを持つ別のクラスを作成します。 ObjectContext Entity Framework の注文の遅延読み込み機能に使用される関数。 この関数は、後で実際の顧客 POCO オブジェクト内で参照によって呼び出されます。 これは、ヘルパー クラスのコード定義です。


    namespace Helper
      {
          public class CustomerHelper
              {
                  public static NorthwindContext CurrentContext;
                  static public void DoLazyLoading(Customer customer, List<Order> orders)
                      {
                          if (CurrentContext == null) return; //no lazy loading
                          var query = from o in CurrentContext.Orders where o.CustomerID == customer.CustomerID select o;
                  
                  foreach (Order o in query)
                          { orders.Add(o); }
                    }
                }
    }
  3. 今すぐ更新する必要があります Customer これにより、顧客に関連するすべての注文を遅延ロードする Entity Framework の機能が得られます。 この機能を参照によって呼び出すために Customer オブジェクトと Orders リストのゲッターを更新する方法を次に示します。 まだ設定する必要があります OrderLazyLoad メインプログラムの次のステップで実行されるヘルパークラスで定義された遅延読み込み関数を指すメソッド。
    namespace MyPOCOs
    {
      [Serializable]
      public class Customer
      {
        public string CustomerID { get; set; }
        public string CompanyName { get; set; }
        public static Action < Customer, List < Order >> OrderLazyLoad = null;
    
        private List < Order > orders; 
        public virtual List< Order > Orders
        {
          get
          {
            if (orders == null)
            {
              orders = new List < Order >();
              OrderLazyLoad(this, orders);
            }
            return orders;
          }
          set
          {
            orders = value;
          }
        }
      }
      [Serializable]
      public class Order…
    }
  4. この拡張機能を使用するには、実際のプログラムを変更する必要があります。
    1. ヘルパークラスでオブジェクトコンテキストを設定します CustomerHelper.CurrentContext) すべてのエンティティが同じオブジェクト コンテキストの下でロードされるように、メイン プログラムで使用されるものと同じである必要があります。つまり、コンシューマ プログラムでも、遅延読み込み用のヘルパー クラスで定義された関数でも同じオブジェクト コンテキストを使用します。
      NorthwindContext Context = new NorthwindContext();
      CustomerHelper.CurrentContext = Context;
    2. また、 OrderLazyLoad ヘルパーの遅延読み込み関数を指すメソッド。これは、 Customer オブジェクトを使用して、ヘルパー クラス オブジェクトを直接参照します。
      Customer.OrderLazyLoad = Helper.CustomerHelper.DoLazyLoading;
  5. 顧客をクエリして分散キャッシュにキャッシュし、Entity Framework の遅延読み込みの追加サポートを使用して関連する注文を表示できるプログラムを実行します。 プログラムがアクセスするたびに、 Orders から Customer、誘導された遅延読み込み機能も呼び出されます。
    static void Main(string[] args)
    {
      Cache mycache = NCache.InitializeCache("mycache");        
      NorthwindContext Context = new NorthwindContext();
      CustomerHelper.CurrentContext = Context;
      Customer.OrderLazyLoad = Helper.CustomerHelper.DoLazyLoading;
    
      var query = from c in Context.Customers where c.CompanyName.StartsWith("b") select c;
      foreach (Customer c in query)
      {
        mycache.Insert(c.CustomerID, c);
        Console.WriteLine("{0}", c.CustomerID);
        foreach (Order order in c.Orders)
        {
          Console.WriteLine("\t{0}", order.OrderDate.ToString());
        }
      }
      Console.ReadLine();
    }

まとめ

Entity Framework で使用される Plain Old CLR Object (POCO) をキャッシュするために分散キャッシュを使用するアプローチについて説明しました。シリアル化の問題を心配する必要がなく、Entity Framework の遅延読み込みのすべての機能を利用できるようになります。 ただし、このアプローチには遅延読み込みを実現するコードを記述する必要がありますが、本質的には、Entity Framework アプリケーションでの高いパフォーマンス、スケーラビリティ、信頼性などの分散キャッシュの利点が得られます。

お問い合わせ(英語)

電話
©著作権 Alachisoft 2002 - . All rights reserved. NCache はダイヤテック株式会社の登録商標です。