实体框架核心显式加载如何忽略更深层次的嵌套实体

时间:2021-04-02 16:17:48

标签: nested entity-framework-core

我有一个包含以下表格的数据库:

用户:

    public class User
    {
        public string UserId { get; set; }
        public string Name { get; set; }
        public Department DefaultDepartment { get; set; }       
        public ICollection<RoleDepartment> RoleDepartment{ get; set; }
    }

角色:

  public class Role
  {
      public int Id { get; set; }
      public string Permissions { get; set; }
      public ICollection<RoleDepartment> RoleDepartment{ get; set; }

  }

角色部门:

   public class RoleDepartment
   {
       public int DepartmentId { get; set; }
       public string UserId { get; set; }
       public int RoleId { get; set; }

       public Department Department { get; set; }
       public User User { get; set; }
       public Role Role { get; set; }
   }

部门

   public class Department
   {
       public int Id { get; set; }
       public string Name { get; set; }
       public ICollection<RoleDepartment> RoleDepartment { get; set; }
   }

当我获得用户数据时

   User user = dbContext.Users
       .Single(u => u.UserId == user_id);
   
   dbContext.Entry(user).Reference(u => u.DefaultDepartment).Load();
   dbContext.Entry(user).Collection(u => u.RoleDepartment).Load();

我收到的数据太多

{

  "UserId": "***",
  "Name": "***",
  "DefaultDepartment": {
    "Id": "**",
    "Name": "***",
    "RoleDepartment": [
      {
        "DepartmentId": "**",
        "UserId": "***",
        "RoleId": "**",
        "User": {
          "UserId": "***",
          "Name": "***",
          "RoleDepartment": [
            {
              "DepartmentId": "**",
              "UserId": "***",
              "RoleId": "**"
            }
          ]
        }
      }
    ]
  },
  "RoleDepartment": [
    {
      "DepartmentId": "**",
      "UserId": "***",
      "RoleId": "**",
      "User": {
        "UserId": "***",
        "Name": "***",
        "DefaultDepartment": {
          "Id": "**",
          "Name": "***",
          "RoleDepartment": [
            {
              "DepartmentId": "**",
              "UserId": "***",
              "RoleId": "**"
            }
          ]
        }
      }
    },
    {
      "DepartmentId": "**",
      "UserId": "***",
      "RoleId": "**",
      "Department": {
        "Id": "**",
        "Name": "***",
        "RoleDepartment": []
      },
      "User": {
        "UserId": "***",
        "Name": "***",
        "DefaultDepartment": {
          "Id": "**",
          "Name": "***",
          "RoleDepartment": []
        }
      }
    }
  ]
}

我想要这样的东西:

{

  "UserId": "***",
  "Name": "***",
  "DefaultDepartment": {
    "Id": "**",
    "Name": "***",
    "RoleDepartment": [
      {
        "DepartmentId": "**",
        "UserId": "***",
        "RoleId": "**"
      }
    ]
  },
  "RoleDepartment": [
    {
      "DepartmentId": "**",
      "UserId": "***",
      "RoleId": "**",
    
      
    },
    {
      "DepartmentId": "**",
      "UserId": "***",
      "RoleId": "**"
    }
  ]
}

有没有办法忽略嵌套的 User 和 Department 实体?

我想在使用显式加载时忽略自动加载的数据。

我错过了什么吗? 谢谢

1 个答案:

答案 0 :(得分:0)

这似乎是一个自引用循环。如果您没有使用 NewtonsoftJson 安装它,

Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson

然后您可以编辑您的 startup.cs,您可以在其中添加 Newtonsoft 以配置 ReferenceLoopHandling

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers().AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
}

还有另一种避免引用循环的方法,那就是告诉序列化器根本不要序列化属性。 Newtonsoft.Json 和 System.Text.Json 中都有一个名为 JsonIgnore 的属性,

   public class RoleDepartment
   {
       public int DepartmentId { get; set; }
       public string UserId { get; set; }
       public int RoleId { get; set; }

       public Department Department { get; set; }
       [JsonIgnore]
       public User User { get; set; }
       public Role Role { get; set; }
   }

但推荐的方法是创建 DTO/ViewModel 并用它们映射您的实体。有关详细信息,请参阅 this

编辑: 对于这种情况,您只能按如下方式停止参考循环。

User user = dbContext.Users
   .Single(u => u.UserId == user_id);
   
dbContext.Entry(user).Reference(u => u.DefaultDepartment).Load();
dbContext.Entry(user).Collection(u => u.RoleDepartment).Load();

var Settings = new Newtonsoft.Json.JsonSerializerSettings
{
    ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(user, user.GetType().BaseType, Settings);

您也可以按如下方式创建匿名对象并返回它。

dbContext.Users.Select(x => new { Prop1 = x.Property1, Prop2 = x.Property2 });