带有过滤器的 Linq 一对多

Linq one to many with filter

我有一个要查询的 Entity Framework 数据库,所以我正在使用 linq-to-entities。

这是我的查询:

// 'Find' 只是 returns IQueryable

的包装方法
var q = r.Find(topic =>
    topic.PageId != null &&
    !topic.Page.IsDeleted &&
    topic.Page.IsActive)

// 这些是标准的 EF 扩展方法,用于包括 链接表。 注:Page_Topic与topic是一对多的关系。

.Include(topic => topic.Page.Route)
.Include(topic => topic.Page_Topic.Select(pt => pt.Page.Route))

// 问题来了:这个 select 语句需要展平 Page_Topic(它确实做到了)。但它似乎在错误的地方这样做。解释一下,如果我要包括另一个依赖于 Page_Topic 的列(例如:'PillarRoutName2',我也必须对该列应用相同的展平逻辑。当然 [=13 的过滤=] 应该以 DRY 方式在更高的查询中完成。

.Select(x => new
{
    TopicName = x.Name,
    HubRouteName = x.Page.Route.Name,
    PillarRouteName = x.Page_Topic.FirstOrDefault(y => y.IsPrimary).Page.Route.Name
}).ToList();

Surely the filtering of Page_Topic should be done higher up the query in a DRY way.

正确!这很容易做到:

.Select(x => new
{
    TopicName = x.Name,
    HubRouteName = x.Page.Route.Name,
    FirstTopic = x.Page_Topic.FirstOrDefault(y => y.IsPrimary)
})
.Select(x => new
{
    TopicName = x.TopicName,
    HubRouteName = x.HubRouteName,
    PillarRouteName = x.FirstTopic.Page.Route.Name,
    PillarRoutName2 = x.FirstTopic. ...
}).ToList();

根据您从 FirstTopic 开始获取属性的位置,您还可以在第一部分中使用 x.Page_Topic.FirstOrDefault(y => y.IsPrimary).Page.Page.Route

请注意,您不需要 Include。它们将被忽略,因为查询是一个投影 (Select(x => new ...)。