序列化对象时检测到循环引用+ ASP.net mvc5 +实体框架

序列化对象时检测到循环引用+ ASP.net mvc5 +实体框架

问题描述:

我正在开发一个测试应用程序使用ASP.Net MVC 5,实体框架与SQL Server。序列化对象时检测到循环引用+ ASP.net mvc5 +实体框架

在我的方案中,数据库中有2个表。 StudentQualification。 一个学生有一个或多个资格。

我需要给studentID和Student(导航性能)的Qualification列表,从数据库中获取一个student应该包含所有他或她有资格。

我实施的控制器方法如下。

 public JsonResult getStudentInfo(int studentId) 
    { 
     db.Configuration.ProxyCreationEnabled = false; 
     Student ss = (Student) (from s in db.Students where s.Id == studentId select s).FirstOrDefault(); 
     ss.Qualifications = (from q in db.Qualifications where q.StudentId == ss.Id select q).ToList(); 
     return Json(ss, JsonRequestBehavior.AllowGet); 
    } 

但是当我试图调用这个函数时,它显示这个错误。

A circular reference was detected while serializing an object of type 'App1.Models.Student'.

如何来解决这个问题。 我需要通过Student实例的资格完整列表。

我的学生模型类,如下所示

public partial class Student 
{ 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 
    public Student() 
    { 
     this.Qualifications = new HashSet<Qualification>(); 
    } 

    public int Id { get; set; } 
    public string Name { get; set; } 
    public Nullable<int> Age { get; set; } 
    public Nullable<byte> Gender { get; set; } 
    public string City { get; set; } 

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 
    public virtual ICollection<Qualification> Qualifications { get; set; } 
} 

Qualification Model类如下

public partial class Qualification 
{ 
    public int Id { get; set; } 
    public Nullable<int> StudentId { get; set; } 
    public string QualificationName { get; set; } 
    public string Institute { get; set; } 
    public Nullable<System.DateTime> EffectiveDate { get; set; } 

    public virtual Student Student { get; set; } 
} 

上述模型类已通过实体数据模型生成的。 我遵循数据库第一方法..

在此先感谢。

+0

Qualification类是什么样的? – Robert

+0

@罗伯特对不起。我刚更新了这个问题。 – JayNaz

+0

是的......我猜罗伯特猜对了;学生 - > qualification->的学生。是你的循环参考。在过去,我编写代码将Student.Qualification.Student设置为null,这样就不会发生这种情况。我相信有更好的解决方案。我不知道它是否可以解决这个问题,但你可以试试这个库:https://github.com/zzzprojects/GraphDiff – theGleep

两件事情:

  1. 我以前可空位为性别类型从Student类,而不是byte
  2. 你说过一个学生有一个或多个资格,但你没有提到同一个资格可以在不同的学生之间分享。如果那么您需要第三个表StudentQualification来存储多对多配置。 否则,你的两个表格设置是好的,但我仍然不会设置StudentIdQualification表中可以为空,因为没有学生,资格是没有什么。一名学生拥有一个或多个资格证书,然后一个资格证书必须有一个学生,如果您反其道而行之。

这是由Microsoft Entity Framework生成的代码。

学生

namespace DL.SO.StudentQualification.Data 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class Student 
    { 
     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 
     public Student() 
     { 
      this.Qualifications = new HashSet<Qualification>(); 
     } 

     public int Id { get; set; } 
     public string Name { get; set; } 
     public Nullable<int> Age { get; set; } 
     public Nullable<bool> Gender { get; set; } 
     public string City { get; set; } 

     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 
     public virtual ICollection<Qualification> Qualifications { get; set; } 
    } 
} 

资格

namespace DL.SO.StudentQualification.Data 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class Qualification 
    { 
     public int Id { get; set; } 
     public int StudentId { get; set; } 
     public string QualificationName { get; set; } 
     public string Institute { get; set; } 
     public Nullable<System.DateTime> EffectiveDate { get; set; } 

     public virtual Student Student { get; set; } 
    } 
} 

这里是控制器方法来获取学生的代码。

public JsonResult GetStudentInfo(int studentId) 
    { 
     using (var db = new AppDbContext()) 
     { 
      // Method syntax 
      var student = db.Students 
       .SingleOrDefault(x => x.Id == studentId); 

      // Query syntax 
      //var student = 
      // from s in db.Students 
      // where s.Id == studentId 
      // select s; 

      return Json(student, JsonRequestBehavior.AllowGet); 
     } 
    } 

你并不需要寻找一名学生,其学历分开(否则为什么要使用EF),因为EF的导航特性可以帮助你。我认为这是你的错误来自哪里。

如果你这样做student.Qualifications,那么你有一个该学生的资格列表。

其他建议:

  1. 不要直接返回数据库模型回到页面,即,它返回查看或恢复其作为JSON对象,因为你不希望暴露属性,你不要不想暴露给公众。使用ViewModel来定义您真正想要公开的属性并将数据传输到视图模型。改为返回视图模型。
  2. 您可能会考虑使用存储库模式并将DbContext注入存储库。那里有很多材料。你可以谷歌和学习。