13

当我尝试序列化通过 EF4 CTP5 返回的对象时,我遇到了循环引用问题。我为我的模型使用代码优先方法和简单的 poco。

我已将 [ScriptIgnore] 属性添加到任何提供对对象的反向引用的属性中,如果我手动实例化 poco,每个属性似乎都可以正常工作,即它们可以很好地序列化为 JSON,并且 scriptignore 属性得到确认。但是,当我尝试序列化从 DAL 返回的对象时,我得到循环引用异常“在序列化 'System.Data.Entity.DynamicProxies.xxxx' 类型的对象时检测到循环引用”

我尝试了几种检索数据的方法,但它们都陷入了这个错误:

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
        TimeSlot ts = tsDao.GetById(id);
        return Json(ts);
    }

下面的方法工作得稍微好一些,而不是时隙动态代理对象导致循环引用它的约会对象。

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
            var ts = from t in tsDao.GetQueryable()
                 where t.Id == id
                 select new {t.Id, t.StartTime, t.Available, t.Appointment};
        return Json(ts);
    }

这个问题的任何想法或解决方案?

更新 如果可能的话,我宁愿使用开箱即用的序列化程序,尽管通过 nuget 的 Json.Net 可以作为替代方案,但我希望它也可以按照我的意图使用它......

4

5 回答 5

4

我在 IIS 托管的 WCF 服务中遇到了类似的问题,并尝试使用 DataContractJsonSerializer 类序列化 POCO 对象。内置的 JSON 序列化程序似乎根本不处理循环引用。我能够通过使用JSON.net序列化程序自己处理序列化并从我的方法返回 json 字符串来解决它。JSON.net 序列化程序可以选择忽略循环引用,因为 json 本身不支持它们。

于 2011-01-05T20:22:36.327 回答
2

无论我做了什么,动态代理一直是一个症结所在,我什至删除了模型中的所有循环引用!但问题仍然存在。

我尝试了 Json.Net,但发生了同样的问题。

最后,我偶然发现了一篇关于使用自定义 JavaScriptConverter 的帖子

http://hellowebapps.com/2010-09-26/produce-json-from-entity-framework-4-0-generated-classes/

实现了代码并让你叔叔一切正常

于 2011-01-06T12:50:47.830 回答
1

我使用了以下 ContractResolver。请注意,我也从 CamelCaseContractPropertyResolver 继承来获得该功能,但您也可以直接从 DefaultContractResolver 继承。

using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json.Serialization;

namespace MyNamespace
{
    /// <summary>
    /// This class enables EntityFramework POCO objects to be serialized. In some cases POCO
    /// objects are subclassed by a proxy which has an additional member _entityWrapper. This
    /// object prevents serialization (circular references and references to non-serializable types).
    /// This removes the _entityWrapper from the list of members to be serialized.
    /// </summary>
    public class ContractResolver : CamelCasePropertyNamesContractResolver
    {
        protected override List<MemberInfo> GetSerializableMembers(Type objectType)
        {
            if (objectType.FullName.StartsWith("System.Data.Entity.DynamicProxies."))
            {
                var members = base.GetSerializableMembers(objectType);
                members.RemoveAll(memberInfo => memberInfo.Name == "_entityWrapper");
                return members;
            }
            return base.GetSerializableMembers(objectType);
        }
    }
}

要使用它,请创建您的序列化程序,然后将 ContractResolver 属性设置为此类的新实例:

var ser = JsonSerializer.Create(sJsonSerializerSettings);            
ser.ContractResolver = new ContractResolver(); 
于 2011-11-15T15:06:19.617 回答
1

我解决了这个问题,而无需求助于外部 JSON 序列化程序。简而言之,我在对象上下文的构造函数中禁用了 ProxyCreation。

我不确定为什么会这样,但我在这里发布了一个后续问题。

于 2011-01-21T00:57:36.237 回答
0

我也遇到过这个问题。此主题的答案包含数字解决方案。但是我在Hongye Sun - Loop Reference handling in Web API的文章中找到了针对不同情况的最佳不同解决方案,并且没有自定义序列化。

于 2013-04-16T11:35:38.943 回答