我遇到了同样的问题。至少在我的情况下,问题在于 EF 用于包装所有模型类的 DynamicProxies。换句话说,您可能认为您正在检索一个Country
类,但实际上,EF 正在动态生成一个名为Country_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85
. 名称的最后一部分显然是在运行时生成的,并且可以预期它在您的应用程序的整个生命周期中保持静态 - 但(这是关键)仅在应用程序域的同一实例上。如果您有两台机器访问同一个进程外缓存,其中一台将存储 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;
}
}
这同时解决了两个问题:(1)它确保只有我特别感兴趣的 EF 对象被缓存,而不是它所附加的整个对象图 - 有时是巨大的;(2) 它缓存的对象是普通类型,而不是动态生成的类型:Country
和 not Country_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85
。
这当然不是完美的,但对于许多场景来说,它似乎是一个合理的解决方法。
不过,如果 MS 的好人想出一种方法来缓存 EF 对象而不使用它,那实际上会很好。