[英]How to get records in EF that match a list of combinations (key/values)?
I have a database table with records for each user/year combination.我有一个数据库表,其中包含每个用户/年份组合的记录。
How can I get data from the database using EF and a list of userId/year combinations?如何使用 EF 和 userId/year 组合列表从数据库中获取数据? 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?
无法围绕如何使用 EF/Linq 编写此内容?
List<UserYearCombination> userYears = GetApprovedYears();
var records = dbcontext.YearResults.Where(?????);
Classes班级
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;
}
This is a notorious problem that I discussed before here .这是我之前在这里讨论过的一个臭名昭著的问题。 Krishna Muppalla's solution is among the solutions I came up with there.
Krishna Muppalla 的解决方案是我在那里提出的解决方案之一。 Its disadvantage is that it's not sargable, ie it can't benefit from any indexes on the involved database fields.
它的缺点是它不是 sargable,即它不能从所涉及的数据库字段上的任何索引中受益。
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);
}
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.我在这里使用
Concat
是因为Union
会浪费时间使结果不同,并且在 EF6 Concat
将生成带有链式UNION
语句的 SQL,而Union
生成嵌套的UNION
语句并且可能会达到最大嵌套级别。
This query may perform well enough when indexes are in place.当索引就位时,此查询可能会执行得足够好。 In theory, the maximum number of
UNION
s 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.理论上,SQL 语句中
UNION
的最大数量是无限的,但IN
子句( Contains
转换为)中的项目数量不应超过几千个。 That means that the content of your data will determine which grouping field performs better, Year
or UserId
.这意味着您的数据内容将决定哪个分组字段表现更好,
Year
或UserId
。 The challenge is to minimize the number of UNION
s while keeping the number of items in all IN
clauses below approx.挑战是最小化
UNION
的数量,同时将所有IN
子句中的项目数量保持在大约以下。 5000. 5000。
you can try this你可以试试这个
//add the possible filters to LIST
var searchIds = new List<string> { "1-2015", "1-2016", "2-2018" };
//use the list to check in Where clause
var result = (from x in YearResults
where searchIds.Contains(x.UserId.ToString()+'-'+x.Year.ToString())
select new UserYearCombination
{
UserId = x.UserId,
Year = x.Year
}).ToList();
Method 2方法二
var d = YearResults
.Where(x=>searchIds.Contains(x.UserId.ToString() + '-' + x.Year.ToString()))
.Select(x => new UserYearCombination
{
UserId = x.UserId,
Year = x.Year
}).ToList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.