LINQ和EF慢

时间:2015-02-18 14:04:22

标签: c# linq entity-framework asp.net-mvc-4

我正在使用MVC4和Entity Framework 5进行项目。我们有一个名为MAIN_TABLE的主表,并且有几个子表(即:CHILD_TABLE1CHILD_TABLE2等。)

由于这些不同子表中的过滤选项很少,我们面临着LINQ查询执行速度的问题。

我必须编写一个查询,使用EF5从Model中过滤数据。 现在我们一次基于单个过滤器进行编码。即我们正在检查每个过滤的列并触发查询。但它太慢了。还有其他选择吗?

string[] strValue = filter_Values;
foreach (SelectedData selectedData in objSelectedDataCollection.DataCollection)
{
    switch (selectedData.ColumnName) // This is the column name in the GridView defined
    {
        case "Outlook":
            indlist = from jd in indlist 
                      where jd.IND_APP_PASS_STATUS.Any(
                                                  ob => strValue.Contains(ob.Outlook))
                      orderby jd.Indman_ID
                      select jd;
            break;
        case "RS_TP":
            indlist = from jd in indlist
                      where jd.IND_APP_PASS_STATUS.Any(
                                                  ob => strValue.Contains(ob.RS_TP))
                      orderby jd.Indman_ID 
                      select jd;
            break;
        case "Code":
            indlist = (from jd in indlist from jk in jd.IND_APP_PASS_STATUS where strValue.Contains(jk.Code) select jd).ToList();
            break;
    }
}

3 个答案:

答案 0 :(得分:1)

EF性能有两个方面 - 服务器和客户端(您的应用程序)。

首先,正如评论中提到的那样,使用SQL分析器来查看生成的查询执行速度有多快。

还要注意返回的记录数。对于返回特别大的结果集switching automatic changes detection off的查询,暂时can give可以显着提升性能。

答案 1 :(得分:1)

从您的评论中,初始数据库查询是

indlist = db.IND_TABLE
            .ToList()
            .Where(x => x.Package_No.Trim() != "")
            .OrderBy(x => Int32.Parse(x.Package_No))
            .Select(x => x)
            .ToList<IND_TABLE>();

第一个.ToList()表示将从数据库返回整个IND_TABLE。然后在代码中完成所有其他过滤。这是性能不佳的原因之一 - 过滤数据库几乎总是比返回所有内容更好。

另请注意,您要多次对结果进行排序。首先设置indlist,然后在objSelectedDataCollection.DataCollection的每次迭代中设置一次。这是不必要的,在完成过滤之前,您根本不应该排序。也许在foreach循环之后,你可以有一行indlist = indlist.OrderBy(x => x.Indman_ID);

将所有这些放在一起可以得到以下结果。

var indlist = db.IND_TABLE
                .Where(x => x.Package_No.Trim() != "");

string[] strValue = filter_Values;
foreach (SelectedData selectedData in objSelectedDataCollection.DataCollection)
{
    switch (selectedData.ColumnName)
    {
        case "Outlook":
            indlist = indlist.Where(il => il.IND_APP_PASS_STATUS.Any(iaps => strValue.Contains(iaps.Outlook)));
            break;
        case "RS_TP":
            indlist = indlist.Where(il => il.IND_APP_PASS_STATUS.Any(iaps => strValue.Contains(iaps.RS_TP)));
            break;
        case "Code":
            indlist = indlist.Where(il => il.IND_APP_PASS_STATUS.Any(iaps => strValue.Contains(iaps.Code)));
            break;
    }
}

indlist = indlist.OrderBy(x => x.Indman_ID).ToList();

当实体框架创建用于查询数据库的SQL(搜索术语&#34;延迟执行&#34;)时,值得一读。只有当您尝试使用结果时才会发生这种情况 - 例如ToList()ToArray()SingleOrDefault()和其他各种事情。行context.TableName.Where(some lambda expression);在此时不会导致数据库查询。您可以在没有数据库调用的情况下使用Where继续过滤,这就是我发布的代码中发生的事情。只会生成SQL并在行indlist = indlist.OrderBy(il => il.Indman_ID).ToList();

中查询数据库

答案 2 :(得分:0)

问题出在我写的查询中。

请检查以下查询。现在我使用&#39;加入&#39;而不是在子表中查询。

注意:答案是如果我们使用Subtables编写查询,则每个父行都会命中数据库中的每个子表行。因此,您的代码性能将根据行数减少.i.e。如果子表有10行,它将对数据库命中10次。但如果我们正在使用&#39;加入&#39;现在,两个表之间的代码只会在每列中出现一次。

var indlist = db.IND_TABLE
            .Where(x => x.Package_No.Trim() != "");

 string[] strValue = filter_Values;
 foreach (SelectedData selectedData in objSelectedDataCollection.DataCollection)
 {
    switch (selectedData.ColumnName)
    {
        case "Outlook":
            indlist = (from jd in indlist join ipas in dbContext.IND_APP_PASS_STATUS on jd.Indman_ID equals ipas.Indman_ID where (strValue.Contains(ipas.Outlook)) orderby jd.Indman_ID select jd).ToList<IND_TABLE>();
            break;

        case "RS_TP":
            indmanlist = (from jd in indmanlist join ipas in dbContext.IND_APP_PASS_STATUS on jd.Indman_ID equals ipas.Indman_ID where (strValue.Contains(ipas.RS_TP)) orderby jd.Indman_ID select jd).ToList<IND_TABLE>();
            break;

        case "Code":
            indmanlist = (from jd in indmanlist join ipas in dbContext.IND_APP_PASS_STATUS on jd.Indman_ID equals ipas.Indman_ID where (strValue.Contains(ipas.Code)) orderby jd.Indman_ID select jd).ToList<IND_TABLE>();
            break;
    }
}

我曾使用SQL Profiler检查数据库的执行情况。然后我意识到了打到数据库的真正问题。