Entity Framework は、Microsoft が提供する非常に人気のあるオブジェクト リレーショナル マッピング エンジンであり、高トラフィック アプリケーションでの使用が増えています。 また、これらの高トラフィック アプリケーションの多くは、メモリ内分散キャッシュを使用することで得られるスケーラビリティを必要とします。 ただし、状況によっては、Entity Framework とメモリ内分散キャッシュに互換性がなくなることがあります。 その方法を説明しましょう。
Entity Framework を Plain Old CLR Objects (POCO) とその遅延読み込み機能とともに使用している場合、Entity Framework は遅延読み込みを実行するためのコードを含むプロキシ オブジェクトを動的に生成します。 また、これらの動的オブジェクト定義はアプリケーション プロセス内にのみ存在するため、プロセス外の分散キャッシュ用にシリアル化することはできません。
以下は、プロキシが生成される例です。 Customer
Entity Framework の遅延読み込みを使用して関連するエンティティ orders
。 動的に生成されたクラス名がどのように表示されるかを確認してください。 このクラス名はアプリケーション プロセス内でのみ使用可能であり、プロセス外では不明です。
ここで問題となるのは、分散キャッシュは常にプロセス外であり、キャッシュする前にすべてのオブジェクトをシリアル化する必要があり、これらのオブジェクトが別のクライアント ボックスからアクセスされるときに、別のマシン上でシリアル化解除する必要がある場合があることです。 したがって、逆シリアル化のために両方のマシンでオブジェクト タイプを知っている必要があります。 また、Entity Framework で動的に生成されたプロキシでは、プロキシは XNUMX 台のマシン上のアプリケーション プロセス内でのみ認識されるため、これは不可能です。 したがって、分散キャッシュで使用するために Entity Framework でのプロキシ生成を無効にする唯一の方法がありますが、これは Entity Framework の遅延読み込み機能も侵害するため、あまり現実的なシナリオではありません。
この問題を解決し、遅延読み込みで Entity Framework を使用するには、まずプロキシを無効にして、シリアル化の問題が発生しないようにする必要があります。 プロキシがオフになっている場合、Entity Framework では遅延読み込みがサポートされないため、アプリケーションに追加のコードを挿入して遅延読み込みを実現する必要があります。
また、この追加コードは、Entity Framework の遅延読み込み機能の実現に役立ち、同時にエンティティの POCO らしさを侵害しないように作成する必要があります。 例を挙げて、このアプローチを段階的に詳しく説明します。
あなたが持っている場合 Customer
を持つオブジェクト Orders
リストをプロパティとして含めると、関連するファイルにアクセスすると、遅延読み込みが機能するはずです。 Orders
Customer の場合、それらはまだ読み込まれていません (つまり、Entity Framework コンテキストに存在しません)。 Customer
オブジェクトは自動的に呼び出しを行い、関連するデータをロードします。 Orders
。以下の例を使用して、プロキシを使用せずに 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 によって使用されるため、問題なく分散キャッシュにキャッシュおよび取得できます。このために、静的なエンティティ フレームワークを持つ別のクラスを作成します。 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); }
}
}
}
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…
}
CustomerHelper.CurrentContext)
すべてのエンティティが同じオブジェクト コンテキストの下でロードされるように、メイン プログラムで使用されるものと同じである必要があります。つまり、コンシューマ プログラムでも、遅延読み込み用のヘルパー クラスで定義された関数でも同じオブジェクト コンテキストを使用します。NorthwindContext Context = new NorthwindContext();
CustomerHelper.CurrentContext = Context;
OrderLazyLoad
ヘルパーの遅延読み込み関数を指すメソッド。これは、 Customer
オブジェクトを使用して、ヘルパー クラス オブジェクトを直接参照します。
Customer.OrderLazyLoad = Helper.CustomerHelper.DoLazyLoading;
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 アプリケーションでの高いパフォーマンス、スケーラビリティ、信頼性などの分散キャッシュの利点が得られます。