简体   繁体   English

EF Core header-detail 查询优化

[英]EF Core header-detail query optimization

I have a header-detail relation in my SQL Server database.我的 SQL Server 数据库中有一个 header-detail 关系。 I have around 10k headers, each of them having 1-1k details.我有大约 10k 个标题,每个标题都有 1-1k 个详细信息。 And the number of unique elements is about 1k.并且唯一元素的数量大约为 1k。

Elements [id]
1
2
3

Headers [id]
1
2
3

Details [id, header_id, element_id]
1 1 1
2 1 2
3 1 3
4 2 1
5 3 1

It's very easy to query a list of headers with their details with such structure:使用这种结构查询带有详细信息的标题列表非常容易:

var searchHeaderIds = new List<int>{1,2,3};
var headers = context.Headers
                     .Where(h => searchHeaderIds.Contains(h.Id))
                     .Include(h => h.Details)
                     .ToList();

But what I want to query is a list of elements (1-200) where every element has a list of headers it belongs to (something like an inversion).但是我要查询的是一个元素列表(1-200),其中每个元素都有一个它所属的标题列表(类似于倒置)。 I can write it in C# as below:我可以用 C# 编写它,如下所示:

var searchElementIds = new List<int>{1,2,3};
var headers = context.Details
                     .Where(d => searchElementIds.Contains(d.element_id))
                     .GroupBy(d => d.element_id)
                     .Select(g => new { 
                                       id = g.Key, 
                                       header_ids = g.Select(x => x.header_id) })
                     .ToList();

But I wonder, what will be the fastest way to do it using the power of SQL/EF?但我想知道,使用 SQL/EF 的强大功能最快的方法是什么?

UPD: I'm ready to use extra data structures, preprocess the data in the database, or do anything else to improve performance. UPD:我准备好使用额外的数据结构,预处理数据库中的数据,或者做任何其他事情来提高性能。

what about:关于什么:

var searchElementIds = new List<int>{1,2,3};
var headers = (
    from header in context.Headers
    join detail in context.Details on header.id equals detail.header_id
    where searchElementIds.Contains(detail.element_id)
    select header).Distinct();

If you want instances of the Element class:如果你想要Element类的实例:

var headers = 
    context.Details
        .Where(d => searchElementIds.Contains(d.element_id))
        .GroupBy(d => d.element_id)
        .Select(g => new Element 
                     { 
                         id = g.Key, 
                         header_ids = g.Select(x => x.header_id
                     })
        .ToList();

Don't cal ToList() in the middle of your query.不要在查询中间调用ToList()

This is most optimal query in your case.在您的情况下,这是最佳查询。 It is closer to original post, but reduced number of retrieved fields for intermediate result:它更接近原始帖子,但减少了中间结果的检索字段数量:

var headers = context.Details
    .Where(d => searchElementIds.Contains(d.element_id))
    .Select(d => new { d.element_id, d.header_id })
    .ToList() // we need this, EF do not support retrieving grouping detals
    .GroupBy(d => d.element_id)
    .Select(g => new Element
    { 
        id = g.Key, 
        header_ids = g.Select(x => x.header_id).ToList()
    })
    .ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM