EF 4.1 - 代码优先 - JSON 循环引用序列化错误 [英] EF 4.1 - Code First - JSON Circular Reference Serialization Error

查看:31
本文介绍了EF 4.1 - 代码优先 - JSON 循环引用序列化错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到一个循环引用序列化错误,但据我所知,我没有任何循环引用.我正在从数据库中检索一组订单并将它们作为 JSON 发送到客户端.所有代码如下所示.

这是错误:

<块引用>

错误

检测到循环引用在序列化一个类型的对象时'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812'.描述:未处理的异常在执行过程中发生当前网络请求.请查看有关更多信息的堆栈跟踪错误及其起源编码.

异常详情:System.InvalidOperationException: A检测到循环引用时序列化一个类型的对象'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812'.

源错误:

产生了未处理的异常在当前的执行过程中网络请求.有关的信息异常的起源和位置可以使用异常来识别下面的堆栈跟踪.

我的课程如下:

订购

公共类订单{[钥匙]公共 int OrderId { 获取;放;}公共 int PatientId { 获取;放;}公共虚拟病人病人{得到;放;}public int CertificationPeriodId { 获取;放;}public virtual CertificationPeriod CertificationPeriod { get;放;}公共 int AgencyId { 获取;放;}公共虚拟代理机构{获取;放;}公共 int PrimaryDiagnosisId { 获取;放;}公共虚拟诊断 PrimaryDiagnosis { get;放;}公共 int ApprovalStatusId { 获取;放;}公共虚拟 OrderApprovalStatus ApprovalStatus { get;放;}公共 int ApproverId { 获取;放;}公共虚拟用户批准人 { get;放;}public int SubmitterId { 获取;放;}公共虚拟用户提交者 { get;放;}public DateTime ApprovalDate { get;放;}公共日期时间提交日期 { 获取;放;}公共布尔 IsDeprecated { 获取;放;}}

患者

公共类患者{[钥匙]公共 int PatientId { 获取;放;}公共字符串名字{获取;放;}公共字符串姓氏 { 获取;放;}公共字符串 MiddleInitial { 获取;放;}public bool IsMale;公共日期时间 DateOfBirth { 获取;放;}公共 int PatientAddressId { 获取;放;}公共地址 PatientAddress { get;放;}public bool IsDeprecated { get;放;}}

认证期限

public class CertificationPeriod{[钥匙]public int CertificationPeriodId { 获取;放;}公共日期时间开始日期 { 获取;放;}公共日期时间结束日期 { 获取;放;}public bool isDeprecated { get;放;}}

机构

公共类代理{[钥匙]公共 int AgencyId { 获取;放;}公共字符串名称 { 获取;放;}公共 int PatientAddressId { 获取;放;}公共虚拟地址地址{获取;放;}}

诊断

公共类诊断{[钥匙]公共 int DiagnosisId { 获取;放;}公共字符串 Icd9Code { 获取;放;}公共字符串 描述 { 获取;放;}公共日期时间日期诊断{获取;放;}公共字符串 Onset { get;放;}公共字符串详细信息{获取;放;}}

订单批准状态

公共类 OrderApprovalStatus{[钥匙]公共 int OrderApprovalStatusId { 获取;放;}公共字符串状态 { 获取;放;}}

用户

公共类用户{[钥匙]公共 int UserId { 获取;放;}公共字符串登录{获取;放;}公共字符串名字{获取;放;}公共字符串姓氏 { 获取;放;}公共字符串 NPI { 获取;放;}公共字符串电子邮件{获取;放;}}

<块引用>

注意:地址类是编辑期间新增的

地址

公共类地址{[钥匙]公共 int AddressId { 获取;放;}公共字符串 StreetAddress { 获取;放;}公共字符串城市{得到;放;}公共字符串状态{获取;放;}公共字符串 Zip { 获取;放;}公共字符串电话{得到;放;}公共字符串标题{获取;放;}公共字符串标签{获取;放;}}

执行序列化的代码在这里:

摘自 OrderController

 public ActionResult GetAll(){返回 Json(ppEFContext.Orders, JsonRequestBehavior.AllowGet);}

谢谢

解决方案

您可以尝试从所有导航属性中删除 virtual 关键字以禁用延迟加载和代理创建,然后使用预先加载来代替显式加载所需的对象图:

public ActionResult GetAll(){返回 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);}

参考您的上一篇文章 看起来您的应用程序无论如何都不依赖延迟加载,因为您在那里引入了虚拟属性来延迟加载对象图,现在可能会导致序列化问题.

编辑

没有必要从导航属性中删除 virtual 关键字(这会使模型完全不可能进行延迟加载).对于代理令人不安的特定情况,例如序列化,禁用代理创建(也禁用延迟加载)就足够了:

ppEFContext.Configuration.ProxyCreationEnabled = false;

这仅禁用特定上下文实例的代理创建ppEFContext.

(我刚刚看到,@WillC 已经在这里提到了.请为他的回答点赞.)

I am getting an a Circular Reference Serialization Error although, to my knowledge I do not have any circular references. I am retrieving a set of Orders from the database and sending them to the client as JSON. All the code is shown below.

This is the error:

Error

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812'. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812'.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

My classes are as follows:

Order

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; }
}

Patient

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; }
}

Certification Period

public class CertificationPeriod
{
    [Key]
    public int CertificationPeriodId { get; set; }
    public DateTime startDate { get; set; }
    public DateTime endDate { get; set; }
    public bool isDeprecated { get; set; }
}

Agency

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; }
}

Diagnosis

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; }
}

OrderApprovalStatus

public class OrderApprovalStatus
{
    [Key]
    public int OrderApprovalStatusId { get; set; }
    public string Status { get; set; }
}

User

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; }

}

NOTE: ADDRESS CLASS IS NEW ADDITION DURING EDIT

Address

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; }
}

The code that executes the serialization is here:

Excerpt from OrderController

    public ActionResult GetAll()
    {
        return Json(ppEFContext.Orders, JsonRequestBehavior.AllowGet);
    }

Thanks

解决方案

You could try to remove the virtual keyword from all navigation properties to disable lazy loading and proxy creation and then use eager loading instead to load the required object graph explicitely:

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);
}

Referring to your previous post it looks like your application isn't relying on lazy loading anyway because you introduced there the virtual properties to load the object graph lazily, possibly causing now the serialization trouble.

Edit

It's not necessary to remove the virtual keyword from the navigation properties (which would make lazy loading completely impossible for the model). It's enough to disable proxy creation (which disables lazy loading as well) for the specific circumstances where proxies are disturbing, like serialization:

ppEFContext.Configuration.ProxyCreationEnabled = false;

This disables proxy creation only for the specific context instance ppEFContext.

(I've just seen, @WillC already mentioned it here. Upvote for this edit please to his answer.)

这篇关于EF 4.1 - 代码优先 - JSON 循环引用序列化错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆