我使用以下参数化linq查询表达式来查询SQL Server中的大约100,000条记录。还有更好的方法吗?
public IList<Article> GetArticles(string language, string category, string subcategory, bool exclusives, int pageIndex, int pageSize = 200)
{
IQueryable<Article> query;
query = db.Articles.Where(t => t.IsActive && t.ArticleStatus);
if (exclusives) { query = query.Where(t => t.IsExclusive); }
if (language.ToUpper() != "ALL")
{
query = query.Where(t => t.Language.ToUpper() == language);
}
if (category.ToUpper() != "ALL")
{
query = query.Where(t => t.Category.ToUpper() == category);
}
if (subcategory.ToUpper() != "ALL")
{
query = query.Where(t => t.SubCategory.ToUpper() == subcategory);
}
query = query.Where(t => t.ArticleDate <= DateTime.Now);
query = query.OrderByDescending(t => t.ArticleNo).Skip((pageIndex - 1) * pageSize).Take(pageSize);
if (query.Any() == false)
{
return null;
}
else
{
return query.ToList();
}
}
答案 0 :(得分:1)
实体框架并不是运行时最快的选择 - 它应该是可维护的,易于编写和快速编写的。如果你想要快速的东西,可以使用不同的ORM,让你手动编写T-SQL(或使用EF的Database.SqlQuery<T>(string)
方法)。
也就是说,您实际上是在两次运行查询。
if (query.Any() == false)
{
return null;
}
else
{
return query.ToList();
}
这些方法中的每一种都将针对数据库执行各种形式的查询。
相反,只用一次调用来测试性能。
var returnList = query.ToList();
if (returnList.Count == 0)
{
return null;
}
else
{
return returnList;
}
这里的改进应该是显而易见的,但是统计数据可能会在你的数据库中搞砸,所以一定要测试。
除此之外,我会检查索引。实体框架以有时不寻常的方式构建其查询,因此我喜欢针对它们运行查询计划资源管理器(或SQL事件探查器)。
最简单的方法是在ToList()
调用几个输入时设置断点,悬停或使用Watch窗口获取query.ToString()
,将其粘贴到可以获取查询计划的内容中(比如VS的数据库工具或SSMS),看看它是否有任何明显的东西。
有时您会重新调整EF以改进查询,但通常情况下您需要重新评估服务器端的索引以满足EF提供给您的内容。
但是,再次,请记住为不同的输入做到这一点 - 您正在改变您的查询,所以您要确保您已覆盖所有基地。