C# 在EF Core中,如何求解包含-然后包含链循环引用?

C# 在EF Core中,如何求解包含-然后包含链循环引用?,c#,entity-framework,asp.net-core,ef-core-3.0,C#,Entity Framework,Asp.net Core,Ef Core 3.0,考虑以下场景。我有3个班级,代表学生和学科之间的多对多(N对N)关系: 由于属性是延迟加载的,我希望每个主题只包含它们的“Name”属性。然而,经过检查,我发现“等级”列表也设置了,其中列出了分配给该科目的所有等级。当然,这会导致对象循环。 我希望避免循环引用,即获取一个列表,其中每个主题的唯一设置属性是“Name”。如何操作?您始终可以手动选择名称,如 context.Student.Select(x => x.Name); 但这不适用于导航属性和表之间自动生成的联接。这

考虑以下场景。我有3个班级,代表学生和学科之间的多对多(N对N)关系:

由于属性是延迟加载的,我希望每个主题只包含它们的“Name”属性。然而,经过检查,我发现“等级”列表也设置了,其中列出了分配给该科目的所有等级。当然,这会导致对象循环。


我希望避免循环引用,即获取一个列表,其中每个主题的唯一设置属性是“Name”。如何操作?

您始终可以手动选择名称,如

   context.Student.Select(x => x.Name);
但这不适用于导航属性和表之间自动生成的联接。这就是“要么全有,要么什么都没有”

或者,您必须完全手动执行连接,而无需导航属性

但你的结构并没有那么复杂,也不容易受到循环的影响。 刚开始的时候用等级,中间有锚元素。

  context.Grade.Include(x => Subject).Include(x =>Student)
这至少是加载整个结构的更简单方法,并且可能是手动连接的起点

也许你可以加一个

   .GroupBy(x => x.Student)
接近你的学生名单


您不能跳过集合的“加载”,因为首先加载的是等级。因此,首先是集合的元素,而不是主体实体。不将数据放入集合是没有意义的。

如果您使用asp.net core 3.0 MVC/Web API,只需按照以下步骤使用
NewtonsoftJson
克服循环引用

1.安装
Microsoft.AspNetCore.Mvc.NewtonsoftJson
软件包(版本取决于您的项目)

2.在启动时添加以下代码

services.AddControllersWithViews().AddNewtonsoftJson(x =>
        {
            x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });

按照Jawad的建议,我最终使用了LINQ Select语句

首先,我写了一些DTO:

public class StudentDTO
{
    public string Name { get; set; }

    public DateTime Birthday { get; set; }

    public long RegistrationNumber { get; set; }

    public IEnumerable<GradeDTO> Grades { get; set; }
}

使用select语句检索该用户的成绩和科目。@Jawad但我必须进行自定义赋值。另一个选择是使用手动连接,正如Holger所建议的,但我要求使用导航属性的解决方案。为什么需要避免循环引用?这是用于JSON序列化的吗?1) 返回视图而不是原始数据库对象。2) 使用属性或序列化选项筛选导航属性。3) 加载后清空导航…您建议选择所有学生的姓名。也许我没有正确地表达自己,但我想获得一个所有学生的列表,每个学生都有一个他们的成绩列表,每个年级的科目名称可以通过该年级的科目属性访问。我想问的是,是否有任何方法可以不使用手动连接来实现这一点,也就是说,通过防止在科目级别加载分数。是的,我理解这一点,并告诉你,没有这种方法。使用include可以跳过延迟加载,并立即加载。“include”关闭了惰性加载,这就是它的含义。当然,您可以使用延迟加载,只需访问主题即可。这很好用,也很简单。但这将对每个主题项提出一个查询。这不是最好的表现。给答案增加了一些东西。
  context.Grade.Include(x => Subject).Include(x =>Student)
   .GroupBy(x => x.Student)
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.0.0
services.AddControllersWithViews().AddNewtonsoftJson(x =>
        {
            x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });
public class StudentDTO
{
    public string Name { get; set; }

    public DateTime Birthday { get; set; }

    public long RegistrationNumber { get; set; }

    public IEnumerable<GradeDTO> Grades { get; set; }
}
public class GradeDTO
{
    public int Value { get; set; }

    public virtual StudentDTO Student { get; set; }
    public virtual SubjectDTO Subject { get; set; }

}
public class SubjectDTO
{
    public string Name { get; set; }

    public virtual IEnumerable<GradeDTO> Grades { get; set; }
}
var res = from student in context.Student
          select new StudentDTO
          {
              Name = student.Name,
              Birthday = student.Birthday,
              RegistrationNumber = student.RegistrationNumber,
              Grades = from grade in student.Grades
                       select new GradeDTO
                       {
                           Value = grade.Value,
                           Subject = new SubjectDTO
                           {
                               Name = grade.Subject.Name
                           }
                       }
          };