序列化对象时检测到循环引用+ ASP.net mvc5 +实体框架
问题描述:
我正在开发一个测试应用程序使用ASP.Net MVC 5,实体框架与SQL Server。序列化对象时检测到循环引用+ ASP.net mvc5 +实体框架
在我的方案中,数据库中有2个表。 Student
和Qualification
。 一个学生有一个或多个资格。
我需要给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; }
}
上述模型类已通过实体数据模型生成的。 我遵循数据库第一方法..
在此先感谢。
答
两件事情:
- 我以前可空位为性别类型从
Student
类,而不是byte
。 - 你说过一个学生有一个或多个资格,但你没有提到同一个资格可以在不同的学生之间分享。如果是那么您需要第三个表
StudentQualification
来存储多对多配置。 否则,你的两个表格设置是好的,但我仍然不会设置StudentId
Qualification
表中可以为空,因为没有学生,资格是没有什么。一名学生拥有一个或多个资格证书,然后一个资格证书必须有一个学生,如果您反其道而行之。
这是由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
,那么你有一个该学生的资格列表。
其他建议:
- 不要直接返回数据库模型回到页面,即,它返回查看或恢复其作为JSON对象,因为你不希望暴露属性,你不要不想暴露给公众。使用
ViewModel
来定义您真正想要公开的属性并将数据传输到视图模型。改为返回视图模型。 - 您可能会考虑使用存储库模式并将
DbContext
注入存储库。那里有很多材料。你可以谷歌和学习。
Qualification类是什么样的? – Robert
@罗伯特对不起。我刚更新了这个问题。 – JayNaz
是的......我猜罗伯特猜对了;学生 - > qualification->的学生。是你的循环参考。在过去,我编写代码将Student.Qualification.Student设置为null,这样就不会发生这种情况。我相信有更好的解决方案。我不知道它是否可以解决这个问题,但你可以试试这个库:https://github.com/zzzprojects/GraphDiff – theGleep