2012-03-13 61 views
0

下面的C#代码在3秒内执行。我列出了SQL Profiler输出。如果我将语句更改为不使用动态SQL,它将以毫秒为单位执行。我找不到任何好的资源来解决这个问题。但是我能够找到一篇文章来解释动态SQL,因为解析器不知道参数的值,所以无法优化查询计划。我该如何解决这个linq查询的性能问题?

public string GetIncorporation(Parcel parcel) 
    { 

    var result = (from c in _context.Districts 
        where c.PARCEL_ID == parcel.PARCEL_ID && c.DB_YEAR == parcel.DB_YEAR && c.DISTRICT_CD.CompareTo("9000") < 0 
        select c).ToList(); 

exec sp_executesql N'SELECT 
[GroupBy1].[A1] AS [C1] 
FROM (SELECT 
    MAX([Filter1].[A1]) AS [A1] 
    FROM (SELECT 
     SUBSTRING([Extent1].[DISTRICT_CD], 0 + 1, 2) + N''00'' AS [A1] 
     FROM [STAGE].[DISTRICT] AS [Extent1] 
     WHERE ([Extent1].[PARCEL_ID] = @p__linq__0) AND ([Extent1].[DB_YEAR] = @p__linq__1) AND ([Extent1].[DISTRICT_CD] < N''9000'') 
    ) AS [Filter1] 
) AS [GroupBy1]',N'@p__linq__0 nvarchar(4000),@p__linq__1 int',@p__linq__0=N'0001-02-0003',@p__linq__1=2012 

我试图建立一个服务层。我不想混合使用一批存储过程和Linq查询

回答

4

您是否将该查询粘贴到SSMS中,运行执行计划并查看它是否建议缺少索引?

另外,如果你不需要从表中的所有列,通过使用选择限制他们:

var result = (from c in _context.Districts 
        where c.PARCEL_ID == parcel.PARCEL_ID && c.DB_YEAR == parcel.DB_YEAR && c.DISTRICT_CD.CompareTo("9000") < 0 
        select c.Parcel_ID).ToList(); 

var result = (from c in _context.Districts 
        where c.PARCEL_ID == parcel.PARCEL_ID && c.DB_YEAR == parcel.DB_YEAR && c.DISTRICT_CD.CompareTo("9000") < 0 
        select new { c.Parcel_ID, c.column2, c.column3}).ToList(); 
+0

是的,我做到了。它建议我在DB_YEAR上创建一个索引,包括PARCEL_ID,DISTRICT_CD – 2012-03-13 15:27:12

+0

事情是...我已经有了一个索引PARCEL_ID,DB_YEAR,DISTRICT_CD这是动态查询的t-sql版本使用的。 – 2012-03-13 15:28:30

0

的LINQ看起来不错,有你得到了正确的索引?

在您粘贴的SSMS查询中,它对DISTRICT_CD没有任何限制,因此请确保它实际上是正在运行的查询。

0

您的性能问题在'CompareTo'部分。此函数不能转换为常规SQL,因此Entity框架将首先实现匹配前2个条件的所有对象(用纯SQL提取)。在这之后(如你所见,需要一些时间),第三个条件在内存中匹配。在你的linq查询中避免使用CompareTo方法,你的问题就会消失。

+0

你错了。但你确实在我的问题上指出了一个错误。我粘贴了错误的sql。奇怪的是,linq引擎完成了将CompareTo()转换为SQL语句的完美工作。 – 2012-03-14 14:35:48

+0

顺便说一句,我认为这是令人惊叹的!那linq可以做出这样的转换!我认为它会按照你的建议工作。 – 2012-03-14 14:45:18

相关问题