C# 实体框架核心在对多对多映射实体查询使用.Include()时返回所有嵌套子级

C# 实体框架核心在对多对多映射实体查询使用.Include()时返回所有嵌套子级,c#,json,entity-framework-core,C#,Json,Entity Framework Core,我使用的是实体框架核心2.0.0。当我在多对多映射实体的导航属性上使用.Include()语句查询我的上下文时,上下文将返回子对象的子对象的所有子对象。。。用于此映射实体的导航属性 例如: MapExerciseWorkout queryResult; using (var context = new FitnessContext("MySqlConnectionString")) { queryResult = context .MapExerciseWorkout.A

我使用的是实体框架核心2.0.0。当我在多对多映射实体的导航属性上使用.Include()语句查询我的上下文时,上下文将返回子对象的子对象的所有子对象。。。用于此映射实体的导航属性

例如:

MapExerciseWorkout queryResult;
using (var context = new FitnessContext("MySqlConnectionString"))
{
    queryResult = context
        .MapExerciseWorkout.AsNoTracking()
        .Include(i => i.Exercise).AsNoTracking()
        .Include(i => i.Workout).AsNoTracking()
        .FirstOrDefault();
}

var result = JsonConvert.SerializeObject(queryResult,
    new JsonSerializerSettings()
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        Formatting = Formatting.Indented
    });
我可以确认未加载与映射实体“MapExecutionWorkout”无关的练习和训练的导航属性,例如练习历史记录和训练权限,因此返回为null

我期望上述示例查询的“结果”为:

{
  "Id": 1,
  "Workout": {
    "Id": 1,
    "Name": "WorkoutA",
    "MapExerciseWorkout": null,
    "WorkoutHistories": null,
    "OwnerGuid": "00000000-0000-0000-0000-000000000000"
  },
  "WorkoutId": 1,
  "Exercise": {
    "Id": 1,
    "Name": "ExerciseA",
    "ExerciseType": 0,
    "MapExerciseWorkout": null,
    "ExerciseHistories": null,
    "OwnerGuid": "00000000-0000-0000-0000-000000000000"
  },
  "ExerciseId": 1,
  "OwnerGuid": "00000000-0000-0000-0000-000000000000"
}
但是,对于包含的练习和训练,您可以获得一个完全递归的MapExercise训练:

{
  "Id": 1,
  "Workout": {
    "Id": 1,
    "Name": "WorkoutA",
    "MapExerciseWorkout": [{"Id":2,"WorkoutId":1,"Exercise":{"Id":2,"Name":"ExerciseB","ExerciseType":0,"MapExerciseWorkout":[{"Id":4,"Workout":{"Id":2,"Name":"WorkoutB","MapExerciseWorkout":[{"Id":3,"WorkoutId":2,"Exercise":{"Id":1,"Name":"ExerciseA","ExerciseType":0,"MapExerciseWorkout":[],"ExerciseHistories":null,"OwnerGuid":"00000000-0000-0000-0000-000000000000"},"ExerciseId":1,"OwnerGuid":"00000000-0000-0000-0000-000000000000"}],"WorkoutHistories":null,"OwnerGuid":"00000000-0000-0000-0000-000000000000"},"WorkoutId":2,"ExerciseId":2,"OwnerGuid":"00000000-0000-0000-0000-000000000000"}],"ExerciseHistories":null,"OwnerGuid":"00000000-0000-0000-0000-000000000000"},"ExerciseId":2,"OwnerGuid":"00000000-0000-0000-0000-000000000000"}],
    "WorkoutHistories": null,
    "OwnerGuid": "00000000-0000-0000-0000-000000000000"
  },
  "WorkoutId": 1,
  "Exercise": {
    "Id": 1,
    "Name": "ExerciseA",
    "ExerciseType": 0,
    "MapExerciseWorkout": [{"Id":3,"Workout":{"Id":2,"Name":"WorkoutB","MapExerciseWorkout":[{"Id":4,"WorkoutId":2,"Exercise":{"Id":2,"Name":"ExerciseB","ExerciseType":0,"MapExerciseWorkout":[{"Id":2,"Workout":{"Id":1,"Name":"WorkoutA","MapExerciseWorkout":[],"WorkoutHistories":null,"OwnerGuid":"00000000-0000-0000-0000-000000000000"},"WorkoutId":1,"ExerciseId":2,"OwnerGuid":"00000000-0000-0000-0000-000000000000"}],"ExerciseHistories":null,"OwnerGuid":"00000000-0000-0000-0000-000000000000"},"ExerciseId":2,"OwnerGuid":"00000000-0000-0000-0000-000000000000"}],"WorkoutHistories":null,"OwnerGuid":"00000000-0000-0000-0000-000000000000"},"WorkoutId":2,"ExerciseId":1,"OwnerGuid":"00000000-0000-0000-0000-000000000000"}],
    "ExerciseHistories": null,
    "OwnerGuid": "00000000-0000-0000-0000-000000000000"
  },
  "ExerciseId": 1,
  "OwnerGuid": "00000000-0000-0000-0000-000000000000"
}
MapExerciseOutwork返回的嵌套子项不是不确定的,而是太多的数据,我不希望也不需要返回它们

我尝试了以下方法,但没有成功:

  • 根据SO问题,我在查询中添加了.AsNoTracking()
  • 我从所有导航属性中删除了“virtual”关键字
  • 我将上下文查询包装在一个using语句中,该语句用于提升已处理的上下文
  • 我想禁用上下文的延迟加载,但EF Core似乎没有设计提供它,所以没有必要禁用它

我如何仅包括运动和训练,而不包括其导航属性以包括其各自的MapExerciseOutwork?

使用
x.include(x=>x.y)
时,还会填充反向导航属性
y.x
。这是“设计的”(所谓导航属性修正的一部分),不能更改。为了完全控制序列化的内容,请使用DTO和投影。感谢您的澄清!我不担心序列化,但我担心查询对SQL数据库的性能影响以及返回数据的大小。按照EF Core的设计方式,这种不必要的反向导航属性行为会消耗执行此简单查询所需的绝大多数资源—性能和大小,不是吗?这对我来说似乎没有必要,尤其是在处理了上下文之后。