如何获取 EF 中与组合(键/值)列表匹配的记录?

Wou*_*out 2 c# linq entity-framework

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

如何使用 EF 和用户 ID/年份组合列表从数据库获取数据? 组合示例

UserId      Year
1           2015
1           2016 
1           2018
12          2016
12          2019
3           2015
91          1999
Run Code Online (Sandbox Code Playgroud)

我只需要上面组合中定义的记录。我无法理解如何使用 EF/Linq 编写此代码?

 List<UserYearCombination> userYears =  GetApprovedYears();

 var records = dbcontext.YearResults.Where(?????);
Run Code Online (Sandbox Code Playgroud)

课程

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;
}
Run Code Online (Sandbox Code Playgroud)

Ger*_*old 6

这是我之前在这里讨论过的一个臭名昭著的问题。Krishna Muppalla 的解决方案是我提出的解决方案之一。它的缺点是它不可控制,即它不能从所涉及的数据库字段上的任何索引中受益。

与此同时,我创造了另一个在某些情况下可能有用的解决方案。基本上,它按字段之一对输入数据进行分组,然后通过分组键和组元素的 Contains 查询来查找和联合数据库数据:

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);
}
Run Code Online (Sandbox Code Playgroud)

Concat在这里使用是因为Union使结果不同会浪费时间,并且在 EF6 中将Concat生成带有链式UNION语句的 SQL,同时Union生成嵌套UNION语句,并且可能会达到最大嵌套级别。

当索引就位时,此查询可能会执行得足够好。理论上,UNIONSQL 语句中的最大数量是无限的,但子句中的项目数量INContains转换为)不应超过数千。这意味着数据的内容将决定哪个分组字段表现更好,Year或者UserId。面临的挑战是最大限度地减少 s 的数量UNION,同时将所有子句中的项目数量保持IN在大约以下。5000。