【问题标题】:Entity Framework Core : get data from related tables with includeEntity Framework Core:从相关表中获取数据,包括
【发布时间】:2021-06-13 01:05:14
【问题描述】:

我正在尝试从五个表中获取数据:Category - subCategory - secondSubCategory - type - heat 这些都与主表(属性)相关。

表 (category - subCategory - secondSubCategory) 像层一样相关 (Category => subCategory => secondSubCategory)

我试图通过以下方式获取数据:

public IActionResult getAllProperties()
{
      var properties = db.properties
                         .Include(cat => cat.category)
                         .Include(sub => sub.subCategory)
                         .Include(sec => sec.SecondSubCategory)
                         .Include(e => e.heating)
                         .Include(e => e.type)        
                         .OrderByDescending(x => x.id)
                         .ToList();
      return Ok(properties);
}

但返回的数据包含类型和加热字段的值,但 (categoryId 和 subCategoryId 和 secondSubCategoryId) 的值为空值,知道这些字段具有值

属性.cs

public class Property
{
    [Key]
    public int id { get; set; }    

    public int typeId { get; set; }
    public type type { get; set; }

    public int heatingId { get; set; }
    public heating heating { get; set; }

    public int? categoryId { get; set; }
    public category category { get; set; }

    public int? subCategoryId { get; set; }
    public subCategory subCategory { get; set; }

    public int? secondSubCategoryId { get; set; }
    public SecondSubCategory SecondSubCategory { get; set; }
}

响应不包括 category 和 subCategory 和 secondSubCategory :

 {
        "id": 14,        
        "typeId": 1,
        "type": {
            "id": 1,
            "typeName": "Flat"
        },
        "heatingId": 4,
        "heating": {
            "id": 4,
            "heatingName": "Conditioning"
        },
        "categoryId": 1,
        "category": null,
        "subCategoryId": 2,
        "subCategory": null,
        "secondSubCategoryId": 3,
        "secondSubCategory": null
    }

响应包括类别和子类别以及第二个子类别:

{
        "id": 14,        
        "typeId": 1,
        "type": {
            "id": 1,
            "typeName": "Flat"
        },
        "heatingId": 4,
        "heating": {
            "id": 4,
            "heatingName": "Conditioning"
        },
        "categoryId": null,
        "category": null,
        "subCategoryId": null,
        "subCategory": null,
        "secondSubCategoryId": null,
        "secondSubCategory": null
}

Category.cs

public class category
  {
    public int id { get; set; }

    public string category_Name { get; set; }

    public IList<subCategory> subCategories { get; set; }
    public Property Property { get; set; }

  }

subCategory.cs:

public class subCategory
    {
    public int id { get; set; }

    public string subCategoryName { get; set; }



    public int CategoryId { get; set; }
    public category category { get; set; }

    public IList<SecondSubCategory> secondSubCategories { get; set; }
    public Property Property { get; set; }
  }

secondSubCategory.cs:

public class SecondSubCategory
  {
    public int id { get; set; }

    public string subCategoryName { get; set; }


    public int subCategoryId { get; set; }
    public subCategory subCategory { get; set; }

    public Property Property { get; set; }
  }

【问题讨论】:

  • 查询中.Include(cat=&gt;cat.category)的目的是什么?
  • 你能显示类别或子类别类
  • @atiyar 目的是从与属性相关的类别中获取数据
  • 但是你已经有 .Include(s=&gt;s.category) 了。
  • @Sergey public class category { public int id { get; set; } public string category_Name { get; set; } public IList&lt;subCategory&gt; subCategories { get; set; } public Property Property { get; set; } }

标签: c# entity-framework-core asp.net-core-webapi


【解决方案1】:

我首先使用代码生成包含您的模型的数据库,并使用一些数据进行测试。如果我不包含 category 和 subCategory 和 secondSubCategory,结果和你的一样,但是当我包含它们时,会有一个期望:

JsonException:检测到不支持的可能对象循环。这可能是由于循环或对象深度大于最大允许深度 32 造成的。

然后我使用 NewtonsoftJson 来处理 ReferenceLoopHandling 问题

services.AddControllersWithViews()
    .AddNewtonsoftJson(options =>
     options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

之后,我就可以从查询中得到category和subCategory和secondSubCategory了。

【讨论】:

    【解决方案2】:

    正如我从您的实体那里得到的那样,您在设计数据库时必须遵循层次结构原则。这是我的建议:

    public class Property
    {
        [Key]
        public int id { get; set; }    
    
        public int typeId { get; set; }
        public type type { get; set; }
    
        public int heatingId { get; set; }
        public heating heating { get; set; }
    
        public int? categoryId { get; set; }
        public category category { get; set; }
    }
    
    public class category
      {
        public int id { get; set; }
        public string category_Name { get; set; }
    
        public IList<subCategory> subCategories { get; set; }
        public Property Property { get; set; }
    
      }
    
    public class subCategory
      {
        public int id { get; set; }
        public string subCategoryName { get; set; }
    
        public int CategoryId { get; set; }
        public category category { get; set; }
    
        public IList<SecondSubCategory> secondSubCategories { get; set; }
      }
    
    
    public class SecondSubCategory
      {
        public int id { get; set; }
        public string secondCategoryName { get; set; }
    
        public int subCategoryId { get; set; }
        public subCategory subCategory { get; set; }
      }
    

    以下是检索层次结构数据的方法:

    public IActionResult getAllProperties()
    {
          var properties = db.properties
                             .Include(cat => cat.category)
                                 .ThenInclude(sub => sub.subCategory)
                                    .ThenInclude(sec => sec.SecondSubCategory)
                             .Include(e => e.heating)
                             .Include(e => e.type)        
                             .OrderByDescending(x => x.id)
                             .ToList();
          return Ok(properties);
    }
    

    【讨论】:

      【解决方案3】:

      您不能直接包含属性类别、子类别和子子类别对象,因为其中一些对象仅在彼此内部。所以试着用老办法做到这一点:

      public IActionResult getAllProperties()
      {
       var properties = ( from p in  db.properties
       join  c in  db.category on p.categoryId equals c.Id into cj
       from c in cj.DefaultIfEmpty()
       join  sc in  db.subCategory on on p.subCategoryId equals sc.Id into scj
       from sc in scj.DefaultIfEmpty()
       join  ssc in  db.secondSubCategory on on p.secondSubCategoryId equals ssc.Id into sscj
       from ssc in sscj.DefaultIfEmpty()
      join  h in  db.heatings on p.heatingId equals h.Id 
      join  t in  db.types on p.typeId equals t.Id 
      orderby  p.id descending
      select new Property {
      id= p.id 
       typeId=p.typeId,
       type=t,
       heatingId = p.heatingId,
       heating=h, 
       categoryId = p.categoryId,
      category =c,
      subCategoryId= p.subCategoryId,
      subCategory=sc,
      secondSubCategoryId=p.secondSubCategoryId,
      SecondSubCategory=ssc 
      }).ToList();
      
       return Ok(properties);
      }
      
      

      或者更短一点:

      var properties = ( from p in  db.properties
       join  c in  db.category on p.categoryId equals c.Id into cj
       from c in cj.DefaultIfEmpty()
       join  sc in  db.subCategory on on p.subCategoryId equals sc.Id into scj
       from sc in scj.DefaultIfEmpty()
       join  ssc in  db.secondSubCategory on on p.secondSubCategoryId equals ssc.Id into sscj
       from ssc in sscj.DefaultIfEmpty()
      orderby  p.id descending
      select new Property {
      id= p.id 
       typeId=p.typeId,
       type=p.type,
       heatingId = p.heatingId,
       heating=p.heading, 
       categoryId = p.categoryId,
      category =c,
      subCategoryId= p.subCategoryId,
      subCategory=sc,
      secondSubCategoryId=p.secondSubCategoryId,
      SecondSubCategory=ssc 
      }).ToList();
      

      【讨论】:

      • 请注意:属性必须有 subCategoryId 和 secondSubCategoryId,所以我无法从表中删除它们
      • 是的,您仍然可以保留所有这些属性,但它们只是额外的计算属性,您不能将它们用于包含。您必须手动分配它们。
      猜你喜欢
      • 2021-12-03
      • 2018-03-19
      • 2023-04-02
      • 2019-02-23
      • 1970-01-01
      • 2020-06-16
      • 2017-09-23
      • 2017-08-01
      • 1970-01-01
      相关资源
      最近更新 更多