当我尝试序列化通过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);
}
这个问题的任何想法或解决方案?
更新 如果可能的话,我宁愿使用开箱即用的序列化器,尽管Json.Net通过nuget可以替代我希望它可以像我预期的那样使用它...
答案 0 :(得分:4)
我遇到了与IIS托管的WCF服务类似的问题,并尝试使用DataContractJsonSerializer类序列化POCO对象。内置的JSON序列化程序似乎根本不处理循环引用。通过使用JSON.net序列化程序自己处理序列化,并从我的方法返回json字符串,我能够绕过它。 JSON.net序列化程序可以选择忽略循环引用,因为json本身不支持它们。
答案 1 :(得分:2)
无论我做了什么,动态代理仍然是一个棘手的问题,我甚至删除了模型中的所有循环引用!但问题仍然存在。
我尝试过Json.Net,但同样的问题也出现了。
最后,我偶然发现了一篇关于使用自定义JavaScriptConverter
的帖子http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/
实施代码并让你叔叔一切顺利
答案 2 :(得分:1)
我解决了这个问题而不必使用外部JSON序列化程序。在nutshull中,我在对象上下文的构造函数中禁用了ProxyCreation。
我不确定为什么会这样,但我发布了一个跟进问题here.
答案 3 :(得分: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();
答案 4 :(得分:0)
我也遇到过这个问题。本主题的答案包含数字解决方案。但是针对不同案例的最佳不同解决方案有解释,而且没有自定义序列化我在文章中找到了 Hongye Sun - Loop Reference handling in Web API 。