人们倾向于使用“包含”作为某种选择的快捷方式。但是,包含所有属性通常会浪费处理能力,因为您不会使用其中的几个属性或者因为您已经知道其值。
以学校与学生为例,这是一种简单的一对多关系。每个学校都有零个或多个学生,每个学生都就读于一所学校,即外键 SchoolId 所指的学校。
因此,如果学校 [10] 有 2000 名学生,则每个学生的 SchoolId 值都等于 10。如果您查询学校 [10] 及其学生,则将传输此值 [10] 超过 2000 次。多么浪费处理能力啊!
在实体框架中,使用Select
查询数据,并且仅选择您实际计划使用的值。仅使用Include
如果您打算更新包含的数据。
当然不要使用“包含”作为“选择所有属性”的某种快捷方式!
回到你的问题
- 每个 Property 都有零个或多个 PropertyParties。
- 每个 PropertyParty 都有零个或多个 Properties。
- 每个属性都有零个或多个 PartyMailingAddresses
- 每个 PartyMailingAddress 都有零个或多个 PropertyMailingAddress
- 每个 PropertyMailingAddress 都有一个布尔属性 Status
您想要查询所有属性(的多个属性),这些属性的内部至少有一个具有真实状态值的 PropertyMailingAddress。
每当您有一系列 Items,其中每个 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,返回的数据不必与数据库表相似。
这样做的优点是您可以隐藏数据库中的更改:只需更改选择,所有用户都不会注意到您在内部深处更改了表。