具有 LINQ 的实体框架在 WHERE 子句中使用 CONTAINS 非常慢且具有大整数列表
Posted
技术标签:
【中文标题】具有 LINQ 的实体框架在 WHERE 子句中使用 CONTAINS 非常慢且具有大整数列表【英文标题】:Entity Framework with LINQ using CONTAINS in WHERE clause very slow with large integer list 【发布时间】:2013-08-14 06:50:59 【问题描述】:我有一个函数,它首先查询数据库中的一个函数,该函数返回一个允许用户查看的员工列表。这在几毫秒内运行。使用此列表,我查询员工表以获取允许该用户查看的所有员工。当我在查询分析器中运行生成的 sql 时,只需要几毫秒。当它从实体框架运行时,它需要超过 8 秒。
最初我有一个 allowedEmployees 列表,但随后阅读 http://mikeinba.blogspot.ca/2009/09/speeding-up-linq-contains-queries-with.html 并尝试使用 HashSet 代替,但性能仍然非常糟糕。如何获得与 sql 查询分析器中的性能相似的性能?我做错了什么?
我正在使用 SQL 2008 和 EF5.0
public IQueryable<Employee> FindAllByWithPermissions(int eID, Expression<Func<Employee, bool>> predicate)
if (predicate != null)
HashSet<int> allowedEmployees = SecurityRepository.GetPermissableEmployees(eID);
return DataContext.Set<Employee>().Where(predicate).Where(p => allowedEmployees.Contains(p.EmployeeID)).AsQueryable<Employee>(); ;
throw new ArgumentNullException("Predicate value must be passed to FindBy<T,TKey>.");
好像写sql有IN子句的时候需要很长的时间。有几千个允许的员工,但为什么生成 sql 需要这么长时间?
【问题讨论】:
嘿,你能在实际查询周围放一些计时器代码并将其与 SSMS 进行比较,它总是可以衡量差异是什么。它还可以帮助您了解何时更好 现在查询运行需要 10799 毫秒。在 SQL 查询分析器中,它需要不到一毫秒。允许的员工列表中大约有 5500 条记录。 你的代码中哪里有计时器块,它就在DataContext.Set<Employee>().Where(predicate)....
附近?
我把它包裹在对 FindAllByWithPermissions 的调用中
【参考方案1】:
返回 IQueryable
而不是 HashSet,然后将 join
与您的员工 IQueryable
一起返回。
var availableEmployees = SecurityRepository.GetPermissableEmployees(eID);
var allEmployees= DataContext.Set<Employee>();
query = from item in allEmployees.Where(predicate)
join t in availableEmployees on item.EmployeeID equals t.EmployeeID
select item;
【讨论】:
GetPermissableEmployee 函数调用 SQL 函数来获取列表。据我所知,您无法将 sql 函数映射到实体框架中。 dbContext.Database.SqlQueryDatabase.SqlQuery
返回一个IEnumerable
,它支持所有的 linq 方法。只需删除 ToList()
调用即可。
将其更改为 IEnumerable 或 IQueryable 的影响可以忽略不计
您是否包含了我在上面发布的用于创建连接而不是使用Contains
的代码?
我决定只使用数据库中的一个表来存储这些值。这让我可以做一个加入。将其从 10 多秒缩短到 2 毫秒以获得我的结果。感谢您的帮助和想法以上是关于具有 LINQ 的实体框架在 WHERE 子句中使用 CONTAINS 非常慢且具有大整数列表的主要内容,如果未能解决你的问题,请参考以下文章
linq 到实体,where 子句中的 where ? (内凡)