5

我有一个使用并置缓存在 azure 中部署的 Web 项目。我有这个网络角色的 2 个实例。

我正在使用实体框架 5,在从数据库中获取一些实体后,我使用并置缓存来缓存它们。

我的实体在名为 Drt.BusinessLayer.Entities 的类库中定义

但是,当我访问我的网络应用程序时,我收到错误消息:

反序列化程序无法加载要反序列化的类型,因为在程序集 'EntityFrameworkDynamicProxies-Drt.BusinessLayer.Entities, Version=1.0. . 检查被序列化的类型是否与被反序列化的类型具有相同的合同,并且使用了相同的程序集。

有时我也会得到这个:

未找到程序集“EntityFrameworkDynamicProxies-Drt.BusinessLayer.Entities,版本=1.0.0.0,文化=中性,PublicKeyToken=null”。

将实体取出/反序列化似乎存在错误。由于它们是我的 Web 角色的 2 个实例,因此 instance1 可能会将一些实体对象放入缓存中,而 instance2 可能会将它们取出。我原以为这会起作用,但我不确定为什么会收到此错误....

任何人都可以提供帮助/建议吗?

4

2 回答 2

4

我遇到了同样的问题。至少在我的情况下,问题在于 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 对象而不使用它,那实际上会很好。

于 2014-03-25T20:26:21.847 回答
0

我特别不熟悉 azure 缓存,但我猜你需要在将实体传递给任何进行序列化的东西之前完全水合你的实体,这是分布式或进程外缓存会做的事情。

因此,当您获取实体或禁用延迟初始化时,只需对所有关系执行 .Include() 即可,您应该没问题。

于 2013-12-16T21:08:05.443 回答