如何在EF中获取与组合(键/值)列表匹配的记录? [英] How to get records in EF that match a list of combinations (key/values)?

查看:98
本文介绍了如何在EF中获取与组合(键/值)列表匹配的记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数据库表,其中包含每个用户/年组合的记录。

I have a database table with records for each user/year combination.

如何使用EF和用户ID /年组合列表从数据库中获取数据?
样本组合

How can I get data from the database using EF and a list of userId/year combinations? Sample combinations:

UserId      Year
1           2015
1           2016 
1           2018
12          2016
12          2019
3           2015
91          1999

我只需要上述组合中定义的记录。

I only need the records defined in above combinations. Can't wrap my head around how to write this using EF/Linq?

 List<UserYearCombination> userYears =  GetApprovedYears();

 var records = dbcontext.YearResults.Where(?????);

public class YearResult
{
    public int UserId;
    public int Year;
    public DateTime CreatedOn;
    public int StatusId;
    public double Production;
    public double Area;
    public double Fte;
    public double Revenue;
    public double Diesel;
    public double EmissionsCo2;
    public double EmissionInTonsN;
    public double EmissionInTonsP;
    public double EmissionInTonsA;
        ....
}

public class UserYearCombination
{
    public int UserId;
    public int Year;
}


推荐答案

这是一个臭名昭著的问题,我之前在这里进行了讨论。克里希纳·穆帕拉(Krishna Muppalla)的解决方案是我在那里提出的解决方案之一。它的缺点是它不可靠,即无法从涉及的数据库字段上的任何索引中受益。

This is a notorious problem that I discussed before here. Krishna Muppalla's solution is among the solutions I came up with there. Its disadvantage is that it's not sargable, i.e. it can't benefit from any indexes on the involved database fields.

同时,我提出了另一种可能对解决问题有帮助的解决方案。在某些情况下。基本上,它按字段之一对输入数据进行分组,然后按分组键和包含组元素的包含查询查找和合并数据库数据:

In the meantime I coined another solution that may be helpful in some circumstances. Basically it groups the input data by one of the fields and then finds and unions database data by grouping key and a Contains query of group elements:

IQueryable<YearResult> items = null;

foreach (var yearUserIds in userYears.GroupBy(t => t.Year, t => t.UserId))
{
    var userIds = yearUserIds.ToList();
    var grp = dbcontext.YearResults
        .Where(x => x.Year == yearUserIds.Key 
                 && userIds.Contains(x.UserId));
    items = items == null ? grp : items.Concat(grp);
}

我使用 Concat 这是因为 Union 会浪费时间使结果变得明显,并且在EF6中, Concat 会生成带有链接的的SQL UNION 语句,而 Union 会生成嵌套的 UNION 语句,并且可能会达到最大嵌套级别。

I use Concat here because Union will waste time making results distinct and in EF6 Concat will generate SQL with chained UNION statements while Union generates nested UNION statements and the maximum nesting level may be hit.

当索引到位时,此查询可能会表现良好。从理论上讲,SQL语句中 UNION 的最大数量是无限的,但是 IN 中的项目数量是无限的子句(包含 的子句)不应超过几千。这意味着
的数据内容将确定哪个分组字段的效果更好,年份 UserId 。面临的挑战是使 UNION 的数量最小化,同时使所有 IN 子句中的项目数保持低于大约。 5000。

This query may perform well enough when indexes are in place. In theory, the maximum number of UNIONs in a SQL statement is unlimited, but the number of items in an IN clause (that Contains translates to) should not exceed a couple of thousands. That means that the content of your data will determine which grouping field performs better, Year or UserId. The challenge is to minimize the number of UNIONs while keeping the number of items in all IN clauses below approx. 5000.

这篇关于如何在EF中获取与组合(键/值)列表匹配的记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆