【问题标题】:Azure caching and entity framework deserialization issueAzure 缓存和实体框架反序列化问题
【发布时间】:2013-05-20 05:33:49
【问题描述】:

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

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

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

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

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

有时我也会这样:

找不到程序集“EntityFrameworkDynamicProxies-Drt.BusinessLayer.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”。

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

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

【问题讨论】:

    标签: azure azure-caching


    【解决方案1】:

    我遇到了同样的问题。至少在我的情况下,问题在于 EF 用于包装所有模型类的 DynamicProxies。换句话说,您可能认为您正在检索Country 类,但实际上,EF 正在动态生成一个名为Country_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85 之类的类。名称的最后一部分显然是在运行时生成的,并且可以预期它在您的应用程序的整个生命周期中保持静态 - 但(这是关键)仅在应用程序域的同一实例上。如果您有两台机器访问同一个进程外缓存,其中一台将存储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 而不是Country_4C17F5A60A033813EC420C752F1026C02FA5FC07D491A3190ED09E0B7509DD85

    这当然不是完美的,但在许多情况下它似乎是一个合理的解决方法。

    不过,如果 MS 的好人想出一种方法来缓存 EF 对象而不用这个,那实际上会很好。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2012-12-16
        • 2011-05-02
        • 1970-01-01
        • 2015-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多