Gui*_*lmi 47 c# serialization json entity-framework asp.net-mvc-3
我得到一个循环引用序列化错误,但据我所知,我没有任何循环引用.我正在从数据库中检索一组订单并将它们作为JSON发送到客户端.所有代码如下所示.
这是错误:
错误
序列化"System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812"类型的对象时检测到循环引用.描述:执行当前Web请求期间发生未处理的异常.请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息.
异常详细信息:System.InvalidOperationException:序列化"System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812"类型的对象时检测到循环引用.
来源错误:
在执行当前Web请求期间生成了未处理的异常.可以使用下面的异常堆栈跟踪来识别有关异常的起源和位置的信息.
我的课程如下:
订购
public class Order
{
[Key]
public int OrderId { get; set; }
public int PatientId { get; set; }
public virtual Patient Patient { get; set; }
public int CertificationPeriodId { get; set; }
public virtual CertificationPeriod CertificationPeriod { get; set; }
public int AgencyId { get; set; }
public virtual Agency Agency { get; set; }
public int PrimaryDiagnosisId { get; set; }
public virtual Diagnosis PrimaryDiagnosis { get; set; }
public int ApprovalStatusId { get; set; }
public virtual OrderApprovalStatus ApprovalStatus { get; set; }
public int ApproverId { get; set; }
public virtual User Approver { get; set; }
public int SubmitterId { get; set; }
public virtual User Submitter { get; set; }
public DateTime ApprovalDate { get; set; }
public DateTime SubmittedDate { get; set; }
public Boolean IsDeprecated { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
患者
public class Patient
{
[Key]
public int PatientId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleInitial { get; set; }
public bool IsMale;
public DateTime DateOfBirth { get; set; }
public int PatientAddressId { get; set; }
public Address PatientAddress { get; set; }
public bool IsDeprecated { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
认证期限
public class CertificationPeriod
{
[Key]
public int CertificationPeriodId { get; set; }
public DateTime startDate { get; set; }
public DateTime endDate { get; set; }
public bool isDeprecated { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
机构
public class Agency
{
[Key]
public int AgencyId { get; set; }
public string Name { get; set; }
public int PatientAddressId { get; set; }
public virtual Address Address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
诊断
public class Diagnosis
{
[Key]
public int DiagnosisId { get; set; }
public string Icd9Code { get; set; }
public string Description { get; set; }
public DateTime DateOfDiagnosis { get; set; }
public string Onset { get; set; }
public string Details { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
OrderApprovalStatus
public class OrderApprovalStatus
{
[Key]
public int OrderApprovalStatusId { get; set; }
public string Status { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
用户
public class User
{
[Key]
public int UserId { get; set; }
public string Login { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string NPI { get; set; }
public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
注意:地址类是编辑期间的新增功能
地址
public class Address
{
[Key]
public int AddressId { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string Phone { get; set; }
public string Title { get; set; }
public string Label { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
执行序列化的代码在这里:
来自OrderController的摘录
public ActionResult GetAll()
{
return Json(ppEFContext.Orders, JsonRequestBehavior.AllowGet);
}
Run Code Online (Sandbox Code Playgroud)
谢谢
Sla*_*uma 48
您可以尝试virtual从所有导航属性中删除关键字以禁用延迟加载和代理创建,然后使用预先加载来明确加载所需的对象图:
public ActionResult GetAll()
{
return Json(ppEFContext.Orders
.Include(o => o.Patient)
.Include(o => o.Patient.PatientAddress)
.Include(o => o.CertificationPeriod)
.Include(o => o.Agency)
.Include(o => o.Agency.Address)
.Include(o => o.PrimaryDiagnosis)
.Include(o => o.ApprovalStatus)
.Include(o => o.Approver)
.Include(o => o.Submitter),
JsonRequestBehavior.AllowGet);
}
Run Code Online (Sandbox Code Playgroud)
参考你之前的帖子看起来你的应用程序似乎并不依赖于延迟加载,因为你在那里引入了虚拟属性来懒惰加载对象图,可能导致现在的序列化问题.
编辑
没有必要virtual从导航属性中删除关键字(这将使模型完全无法进行延迟加载).对于代理令人不安的特定情况,如序列化,它足以禁用代理创建(这也会禁用延迟加载):
ppEFContext.Configuration.ProxyCreationEnabled = false;
Run Code Online (Sandbox Code Playgroud)
这将仅为特定上下文实例禁用代理创建ppEFContext.
(我刚才看到,@ WillC已经在这里提到过了.请为这个编辑提供支持请回答他.)
Wil*_*llC 41
当您知道需要从特定上下文序列化时,可以禁用该特定查询的代理创建,如下所示.这对我有用,并且比修改我的模型类更好.
using (var context = new MeContext())
{
context.Configuration.ProxyCreationEnabled = false;
return context.cars.Where(w => w.Brand == "Ferrari")
}
Run Code Online (Sandbox Code Playgroud)
此方法取消了此特定上下文实例的代理对象类型,因此返回的对象是实际的类,因此序列化不是问题.
即:
{Models.car}
Run Code Online (Sandbox Code Playgroud)
代替
{System.Data.Entity.DynamicProxies.car_231710A36F27E54BC6CE99BB50E0FE3B6BD4462EC??A19695CD1BABB79605296EB}
Run Code Online (Sandbox Code Playgroud)
问题是你实际上正在序列化一个实体框架生成的代理对象.不幸的是,当与JSON序列化程序一起使用时,这会出现一些问题.为了JSON兼容性,您可以考虑将实体映射到特殊的简单POCO类.
我认为他们已经在最新版本中解决了这个问题.
查看" 序列化和反序列化JSON - >序列化和保留对象引用 " 部分下的帮助文档.
初始化JSON.Net Serializer时设置此设置:
PreserveReferencesHandling = PreserveReferencesHandling.Objects;
Run Code Online (Sandbox Code Playgroud)
所以一个例子是这样的:
var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };
string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings);
Run Code Online (Sandbox Code Playgroud)
我确认这适用于我的代码第一个解决方案,以及导航属性中的循环引用.如果你看看生成的JSON,它应该在任何地方都有"$ id"和"$ ref"属性.
| 归档时间: |
|
| 查看次数: |
45206 次 |
| 最近记录: |