我有一个数据库表,其中包含每个用户/年份组合的记录。
如何使用EF和userId / year组合列表从数据库中获取数据? 样本组合:
UserId Year
1 2015
1 2016
1 2018
12 2016
12 2019
3 2015
91 1999
我只需要以上组合中定义的记录。不能用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;
}
答案 0 :(得分:2)
这是我在here之前讨论的一个臭名昭著的问题。克里希纳·穆帕拉(Krishna Muppalla)的解决方案是我在那里提出的解决方案之一。它的缺点是它不可靠,即不能从涉及的数据库字段上的任何索引中受益。
同时,我提出了另一种在某些情况下可能有用的解决方案。基本上,它按字段之一对输入数据进行分组,然后按分组键和包含组元素的包含查询查找并合并数据库数据:
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
会生成带有链接的UNION
语句的SQL,而Union
会生成嵌套的UNION
条语句和最大嵌套级别可能会被击中。
在建立索引后,此查询的性能可能会很好。从理论上讲,SQL语句中UNION
的最大数量是不受限制的,但是IN
子句(Contains
转换为)中的项目数不应超过几千。那意味着
数据的内容将确定哪个分组字段表现更好,Year
或UserId
。面临的挑战是使UNION
的数量最小化,同时使所有IN
子句中的项目数保持低于大约。 5000。
答案 1 :(得分:1)
您可以尝试
//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();
方法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();