C# 如何使用linq for entities或EF Core 2从子级到父级选择层次结构?

C# 如何使用linq for entities或EF Core 2从子级到父级选择层次结构?,c#,linq,entity-framework-core,parent-child,C#,Linq,Entity Framework Core,Parent Child,有四个实体(模型)的层次结构。所有实体都有一对多的关系。它看起来如下: public class Region { public Guid Id { get; set; } public int RegionId { get; set; } public virtual ICollection<District> Districts { get; set; } } public class District

有四个实体(模型)的层次结构。所有实体都有一对多的关系。它看起来如下:

public class Region
    {
        public Guid Id { get; set; }
        public int RegionId { get; set; }
        public virtual ICollection<District> Districts { get; set; }
    }
    public class District
    {
        public Guid Id { get; set; }
        public int DistrictId { get; set; }
        public virtual ICollection<Building> Buildings { get; set; }
        public int RegionId { get; set; }
        public Region Region { get; set; }
    }
    public class Building
    {
        public Guid Id { get; set; }
        public int BuildingId { get; set; }
        public int DistrictId { get; set; }
        public virtual ICollection<Flat> Flats { get; set; }
        public District District { get; set; }
    }
    public class Flat
    {
        public Guid Id { get; set; }
        public int FlatId { get; set; }
        public int BuildingId { get; set; }
        public Building Building { get; set; }
    }
但由于某种原因,这是回报突破的结果

[{"id":"6cbb1431-36d4-490c-a047-c211e4db3bdd","flatId":29570,"roomsCount":1,"totalArea":41.95,"kitchenArea":11.85,"floor":21,"buildingId":130,"price":5725650.00,"building":{"id":"03baca1e-02e9-4ee0-ae47-920e3eb0d5bb","buildingId":130,"name":"NNN","queue":1,"housing":"1","districtId":13003,"flats":[
它在
公共虚拟ICollection Flats{get;set;}
上由于某种原因而中断。我不能移除它,因为它是FK需要的

以下查询工作正常:

_context.Flat
   .Join(
      _context.Building,
      f => f.BuildingId,
      b => b.BuildingId,
      (f, b) =>
         new
         {
             f = f,
             b = b
         }
   )
   .Join(
      _context.District,
      temp0 => temp0.b.DistrictId,
      d => d.DistrictId,
      (temp0, d) =>
         new
         {
             temp0 = temp0,
             d = d
         }
   )
   .Join(
      _context.Region,
      temp1 => temp1.d.RegionId,
      r => r.RegionId,
      (temp1, r) =>
         new 
         {
             Id = temp1.temp0.f.Id,
             FlatId = temp1.temp0.f.FlatId,
             Floor = temp1.temp0.f.Floor,
             RoomsCount = temp1.temp0.f.RoomsCount,
             TotalArea = temp1.temp0.f.TotalArea,
             KitchenArea = temp1.temp0.f.KitchenArea,
             Price = temp1.temp0.f.Price,
             Building = new
             {
                 Id = temp1.temp0.b.Id,
                 BuildingId = temp1.temp0.b.Id,
                 Name = temp1.temp0.b.Name,
                 Queue = temp1.temp0.b.Queue,
                 Housing = temp1.temp0.b.Housing,
                 District = new
                 {
                     Id = temp1.d.Id,
                     DistrictId = temp1.d.DistrictId,
                     Name = temp1.d.Name,
                     Regions = new
                     {
                         Id = r.Id,
                         RegionId = r.Id,
                         Name = r.Name
                     }
                 }
             }
         }
   ).GetPaged(PageNumber, PageSize)
这是我想要的回报:

{
    "id": "a49a0a48-370b-46da-b6da-ea4040cc1431",
    "flatId": 84095,
    "roomsCount": 3,
    "totalArea": 76.5,
    "kitchenArea": 11.07,
    "floor": 18,
    "buildingId": 0,
    "price": 5567500,
    "building": {
        "id": "037c4074-3ff5-4fbd-92ea-88c8f746b883",
        "buildingId": 200,
        "name": "NNNN",
        "queue": 3,
        "housing": "4",
        "districtId": 0,
        "flats": null,
        "district": {
            "id": "db031e09-1d6c-41f4-9e45-ec6170e3df8b",
            "districtId": 5005,
            "name": "Distr",
            "buildings": null,
            "regionId": 0,
            "region": {
                "id": "5ac5766f-e62e-4da9-86cf-e4a85423503a",
                "regionId": 5001,
                "name": "Region",
                "districts": null
            }
        }
    }
}
但它看起来很笨重。 我如何使用EF功能实现这一点?或者是为了降低linq?为什么
include()
返回中断结果


p.S.
.GetPaged(页码,20)
是分页的扩展方法,他工作得很好。

我的建议如下

var flag = (from f in _context.Flags
       join b in _context.Buildings
       on b.BuildingId equals f.BuildingId
       join d in _context.Districts
       on d.DistrictId equals b.DistrictId 
       join r in _context.Regions
       on r.RegionId equals d.RegionId
       select new 
       { ... 
       }).GetPaged(PageNumber, 20);

您可以从Building、District和Region中获取任何属性以填充到结果对象中。

下面是我的建议

var flag = (from f in _context.Flags
       join b in _context.Buildings
       on b.BuildingId equals f.BuildingId
       join d in _context.Districts
       on d.DistrictId equals b.DistrictId 
       join r in _context.Regions
       on r.RegionId equals d.RegionId
       select new 
       { ... 
       }).GetPaged(PageNumber, 20);

您可以从Building、District和Region中获取任何属性以填充到结果对象。

每个建筑只有一个District和一个Region,为什么不添加District=f.Building.District,Region=f.Building.District.Region?我不能仅仅添加,因为通过这个模型,EF代码首先生成数据库。不清楚实际的问题是什么
Include
query很好,不确定“它工作得很慢”是什么意思。您是否测量了EF查询执行时间?生成的SQL?最后,JSON序列化中可能会出现问题(如果有)。在尝试使用冗余连接和投影解决问题之前,先将问题本地化。我已更正了文本。请参见上文。@Seva,对于Include方法,我认为您应该为结果创建一个动态类。每个建筑只有一个地区和一个区域,为什么不添加District=f.Building.District,Region=f.Building.District.Region?我不能仅仅添加,因为通过这个模型,EF代码首先生成数据库。不清楚实际的问题是什么
Include
query很好,不确定“它工作得很慢”是什么意思。您是否测量了EF查询执行时间?生成的SQL?最后,JSON序列化中可能会出现问题(如果有)。在尝试使用冗余连接和投影解决问题之前,先将问题本地化。我已更正了文本。请参见上文。@Seva,对于Include方法,我认为您应该为结果创建一个动态类。您已经显示了一个标准的LINQ连接查询。但在EF中,我们不使用连接,而是使用导航属性。因为
b
f.Building
d
b.District
r
d.Region
。和联接由EF基于模型元数据自动提供。因此,这相当于包含的原始查询。也许应该尝试一下,比较两种方法生成的SQL是否有任何差异。我只想说,我的查询方式可能是性能最好的方式。它很有效。非常感谢。我已经改正了课文。请参见上面。您已经展示了一个标准的LINQ连接查询。但在EF中,我们不使用连接,而是使用导航属性。因为
b
f.Building
d
b.District
r
d.Region
。和联接由EF基于模型元数据自动提供。因此,这相当于包含的原始查询。也许应该尝试一下,比较两种方法生成的SQL是否有任何差异。我只想说,我的查询方式可能是性能最好的方式。它很有效。非常感谢。我已经改正了课文。请看上面。