【问题标题】:Linq one to many with filterLinq 一对多与过滤器
【发布时间】:2022-01-11 18:30:09
【问题描述】:

我有一个要查询的实体框架数据库,所以我使用的是 linq-to-entities。

这是我的查询:

// 'Find' 只是一个返回 IQueryable 的包装方法

var q = r.Find(topic =>
    topic.PageId != null &&
    !topic.Page.IsDeleted &&
    topic.Page.IsActive)

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

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

// 这里的问题:这个选择语句需要展平Page_Topic(它确实如此)。但它似乎在错误的地方做。解释一下,如果我要包含另一个依赖于 Page_Topic 的列(例如:'PillarRoutName2',我也必须对该列应用相同的展平逻辑。当然,Page_Topic 的过滤应该在更高的位置完成以 DRY 方式查询。

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

【问题讨论】:

    标签: c# asp.net linq entity-framework-6


    【解决方案1】:

    当然,Page_Topic 的过滤应该以 DRY 方式在查询的更高层进行。

    正确!这样做很容易:

    .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

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

    【讨论】:

    • 感谢 Gert 的回答和解释 - 我今天学到了一些东西 :)
    • 所以,这个查询不会产生重复的 JOIN 与 ROW_NUMBER ?
    • @SvyatoslavDanyliv 对不起,我不明白这个问题。据我所见,输出符合预期。
    • @SvyatoslavDanyliv 这是 EF6 经典,它生成一个带有 OUTER APPLYTOP(1) 的查询
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 2022-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多