参数化Linq查询 - 有更好的性能选项吗?

时间:2016-05-28 20:04:43

标签: c# linq entity-framework-6

我使用以下参数化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();
        }
    }

1 个答案:

答案 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提供给您的内容。

但是,再次,请记住为不同的输入做到这一点 - 您正在改变您的查询,所以您要确保您已覆盖所有基地。