在 ThenInclude 三层嵌套的基础上进行过滤。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在 ThenInclude 三层嵌套的基础上进行过滤。相关的知识,希望对你有一定的参考价值。

我试图向下过滤三个子级别,只找到 PropertyMailingAddress.Status== True 的子元素。

但它仍然在PropertyMailingAddress.Status下返回False的值。

如何将过滤三层向下转换,用ThenInclude进行嵌套过滤?

类结构是这样嵌套的。

  1. 属性
  2. 财产方
  3. 党员邮件地址
  4. PropertyMailingAddress
var result = await propertyRepository.GetAll()
                .Include(pm => pm.PropertyParty).ThenInclude(x => x.Party).ThenInclude(x => x.PartyMailingAddress).ThenInclude(x => x.PropertyMailingAddress)
                .Where (a=> a.PropertyParty.Any(x=> (x.Party.PartyMailingAddress.Any(z => z.PropertyMailingAddress.Any(h => h.Status.HasValue && h.Status.Value && h.Status == true))))
答案

人们倾向于使用Include作为Select的某种快捷方式。然而,包含所有的属性通常是相当浪费处理能力的,因为你不会使用其中的几个属性,或者因为你已经知道其值。

以一个有学生的学校为例,这是一个直接的一对多关系。每个学校都有0个或多个学生,每个学生正好就读于一个学校,即外键SchoolId所指的学校。

所以如果学校[10]有2000个学生,那么每个学生的SchoolId的值就等于10。如果你查询学校[10]和它的学生,你将会把这个值[10]转移2000次以上。真是浪费处理能力啊!

在实体框架中,使用 Select 来查询数据,并且只选择您实际计划使用的值。只使用 Include 如果你打算更新包含的数据。

当然,不要把 "包含 "当作 "选择所有属性 "的某种快捷方式来使用

回到你的问题

  • 每个属性都有零个或多个属性方。
  • 每个PropertyParty都有零个或多个Property。
  • 每个属性都有零个或更多的PartyMailingAddresses。
  • 每个PartyMailingAddress都有零个或多个PropertyMailingAddresses。
  • 每个PropertyMailingAddress都有一个Boolean属性Status。

你想查询(几个属性的)所有属性,这些属性至少有一个具有真实状态值的PropertyMailingAddress。

当你有一个Item序列,其中每个Item都有一个OtherItems的子序列,而你想把所有的OtherItems当作一个序列来调查,可以考虑使用SelectMany。

var propertiesWithTrueStatus = propertyRepository.GetAll()
    .Where(property => property.SelectMany(property => property.PropertyParties)

        // result: one big sequence of all PropertyParties of all properties
        .SelectMany(propertyParty => propertyParty.PartyMailingAddresses)

        // result: one big sequence of all PartyMailingAddresses of all 
        // PropertyParties of all Properties
        .SelectMany(partyMailingAddress => partyMailingAddress.PropertyMailingAddresses)
        .Select(propertyMailingAddress => propertyMailingAddress.Status)

        // result: one big sequence of all Statusses of all PropertyMailingAddresses
        // of all ... of all Properties

        // Keep only the true status values:
        .Where(status => status)

        // keep only the Properties that have at least one true Status value
        .Any())
        // end of Where(...)

所以现在你只有那些深藏在里面至少有一个真状态值的属性。继续查询 Select (或者如果你真的想。Include)

    .Select(property => new
    
        // Select only the properties that you actually plan to use
        Id = property.Id,
        Name = property.Name,
        ...

        PropertyParties = property.PropertyParties.Select(propertyParty => new
        
            // again only the properties that you plan to use:
            Id = propertyParty.Id,
            ...

            // no need to Select this, you already know the value
            // PropertyId = propertyParty.PropertyId

            PartyMailingAddresses = propertyParty.PartyMailingAddresses
                .Select( partyMailingAddress => new  ...  )
                .ToList(),
        )
        .ToList(),
    );

除此以外,Select比Include更有效,它给了你更多的自由,如果需要的话,可以偏离你的数据库表。如果你不需要在你的最终结果中包含所有的PropertyMailingAddresses,干脆不要选择它们。如果你只想知道 PropertyParties 的总数,使用 PropertyPartyCount = propertyParties.Count. 使用Select,返回的数据不一定要和你的数据库表相似。

这样做的好处是,你可以隐藏数据库中的变化:只需改变Select,你所有的用户都不会注意到你改变了你的表。

以上是关于在 ThenInclude 三层嵌套的基础上进行过滤。的主要内容,如果未能解决你的问题,请参考以下文章

win10+黑苹果双系统

一键安装黑苹果系统3.0教程

python基础--函数进阶

ThenInclude 在 EF Core 查询中无法识别

Select() 在 ThenInclude() 中不起作用

如何在 EF Core 中调用 ThenInclude 两次?