我有一份我这样建立的员工名单:
var employees = db.employees.Where(e => e.isActive == true).ToList();
var latestSales = from es in db.employee_sales.Where(x => x.returned == false);
现在我想要的是这样的结果:
int employeeId
List<DateTime> lastSaleDates
所以我尝试了这个,但查询需要很长时间才能完成:
var result =
(from e in employees
select new EmployeeDetails
{
EmployeeId = e.employeeId,
LastSaleDates =
(from lsd in latestSales.Where(x => x.EmployeeId == e.EmployeeId)
.Select(x => x.SaleDate)
select lsd).ToList()
};
上述工作,但完成需要1分钟。
这是一种更有效的方法吗?
答案 0 :(得分:6)
您可以使用join来获取单个查询中的所有数据
var result = from e in db.employees.Where(x => x.isActive)
join es in db.employee_sales.Where(x => x.returned)
on e.EmployeeId equals es.EmployeeId into g
select new {
EmployeeId = e.employeeId,
LastSaleDates = g.Select(x => x.SaleDate)
};
很遗憾,您不能将ToList()
方法与Linq to Entities一起使用。因此,要么手动将匿名对象映射到EmployeeDetails
,要么将LastSalesDates
类型更改为IEnumerable<DateTime>
。
答案 1 :(得分:3)
您对ToList
的来电正在将内容拉入记忆中。您应该选择构建Linq表达式,而不是将整个查询拉入内存。在第二个查询中,您将为每个员工发出一个新查询,因为您随后在Linq-to-objects域中运行(而不是在EF中)。请尝试删除对ToList
。
您还应该考虑使用外键关联属性来使此查询更好。关联属性是EF中最强大和最有用的部分。详细了解他们here。如果您具有正确的关联属性,那么您的查询看起来就像这样:
var result = from e in employees
select new EmployeeDetails
{
EmployeeId = e.employeeId,
LastSaleDates = e.AssociatedSales
}
您也可以考虑使用连接。阅读Linq的Join
方法here。
答案 2 :(得分:1)
您的模型中是否存在员工与latestSales之间的关联?您是否检查过SQL Profiler或其他分析工具以查看生成的SQL?确保ToList()没有为每个员工发出单独的查询。
如果你可以将结果结构作为IEnumerable<EmployeeId, IEnumerable<DateTime>>
,你可以考虑将其修改为:
var result = (from e in employees
select new EmployeeDetails
{
EmployeeId = e.employeeId,
LastSaleDates = (from lsd in latestSales
where e.employeeId equals lsd.EmployeeId
select lsd.SaleDate)
};
我在http://www.thinqlinq.com/Post.aspx/Title/LINQ-to-Database-Performance-hints处提供了一些更为一般性的建议,以帮助追踪问题。