5

コロケーション キャッシュを使用して Azure にデプロイされた Web プロジェクトがあります。この Web ロールのインスタンスが 2 つあります。

私はエンティティ フレームワーク 5 を使用しており、db からいくつかのエンティティをフェッチする際に、コロケーション キャッシュを使用してそれらをキャッシュします。

私のエンティティは、Drt.BusinessLayer.Entities というクラス ライブラリで定義されています。

ただし、Web アプリにアクセスすると、次のエラーが表示されます。

タイプ 'System.Data.Entity.DynamicProxies.Country_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85' がアセンブリ 'EntityFrameworkDynamicProxies-Drt.BusinessLayer.Entities', CultureTokennull.0, Version=0. . シリアル化されている型が逆シリアル化されている型と同じコントラクトを持ち、同じアセンブリが使用されていることを確認してください。

また、時々私もこれを取得します:

アセンブリ 'EntityFrameworkDynamicProxies-Drt.BusinessLayer.Entities、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null' が見つかりません。

エンティティのアウト/デシリアライズ中にエラーが発生したようです。これらは私の Web ロールの 2 つのインスタンスであるため、instance1 はいくつかのエンティティ オブジェクトをキャッシュに配置し、instance2 はそれらを取得する可能性があります。これが機能することを期待していましたが、なぜこのエラーが発生するのかわかりません....

誰でも助けたりアドバイスしたりできますか?

4

2 に答える 2

4

私は同じ問題に遭遇しました。少なくとも私の場合、問題は EF がすべてのモデル クラスをラップする DynamicProxies でした。つまり、クラスを取得していると思うCountryかもしれませんが、内部では、EF は実際には のような名前のクラスを動的に生成していCountry_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85ます。名前の最後の部分は明らかに実行時に生成され、アプリケーションの存続期間中は静的なままであることが期待できますが (これが重要です)、アプリ ドメインの同じインスタンスでのみです。2 台のマシンが同じアウトプロセス キャッシュにアクセスしている場合、一方は type のオブジェクトを格納しますが、Country_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85その型はもう一方のマシンには存在しません。その動的Countryクラスは次のようになりますCountry_JF7ASDF8ASDF8ADSF88989ASDF8778802348JKOJASDLKJQAWPEORIU7879243AS、したがって、シリアル化されたオブジェクトを逆シリアル化できる型はありません。Web アプリが実行されているアプリ ドメインを再起動すると、同じことが起こります。

MS の大きな頭脳がより良い解決策を思い付くことができると確信していますが、私が使用してきたのは、キャッシュする前に EF オブジェクトの「浅いクローン」を作成することです。私が使用している C# メソッドは次のようになります。

public static class TypeHelper
{
    public static T ShallowClone<T>(this T obj) where T : class
    {
        if (obj == null) return null;
        var newObj = Activator.CreateInstance<T>();
        var fields = typeof(T).GetFields();
        foreach (var field in fields)
        {
            if (field.IsPublic && (field.FieldType.IsValueType || field.FieldType == typeof(string)))
            {
                field.SetValue(newObj, field.GetValue(obj));
            }
        }
        var properties = typeof(T).GetProperties();
        foreach (var property in properties)
        {
            if ((property.CanRead && property.CanWrite) && 
                (property.PropertyType.IsValueType || property.PropertyType == typeof(string)))
            {
                property.SetValue(newObj, property.GetValue(obj, null), null);
            }
        }
        return newObj;
    }
}

これにより、2 つの問題が同時に処理されます。(1) 特に関心のある EF オブジェクトのみがキャッシュされ、オブジェクト グラフ全体 (場合によっては巨大) がキャッシュされることはありません。(2) キャッシュするオブジェクトが共通の型であり、動的に生成された型ではない: Countryand not Country_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85.

これは確かに完璧ではありませんが、多くのシナリオでは妥当な回避策のようです。

ただし、MS の優秀な人々が、これを使用せずに EF オブジェクトをキャッシュする方法を考え出すとしたら、それは実際には素晴らしいことです。

于 2014-03-25T20:26:21.847 に答える