简体   繁体   English

实体框架LINQ到实体的联接查询超时

[英]Entity Framework LINQ to Entities Join Query Timeout

I am executing the following LINQ to Entities query but it is stuck and does not return response until timeout. 我正在执行以下LINQ to Entities查询,但是它被卡住了,直到超时才返回响应。 I executed the same query on SQL Server and it return 92000 in 3 sec. 我在SQL Server上执行了相同的查询,它在3秒内返回92000。

            var query = (from r in WinCtx.PartsRoutings
                     join s in WinCtx.Tab_Processes on r.ProcessName equals s.ProcessName
                     join p in WinCtx.Tab_Parts on r.CustPartNum equals p.CustPartNum
                     select new { r}).ToList();

SQL Generated: SQL生成:

SELECT [ I omitted columns]
    FROM   [dbo].[PartsRouting] AS [Extent1]
INNER JOIN [dbo].[Tab_Processes] AS [Extent2] ON ([Extent1].[ProcessName] = [Extent2].[ProcessName]) OR (([Extent1].[ProcessName] IS NULL) AND ([Extent2].[ProcessName] IS NULL))
INNER JOIN [dbo].[Tab_Parts] AS [Extent3] ON ([Extent1].[CustPartNum] = [Extent3].[CustPartNum]) OR (([Extent1].[CustPartNum] IS NULL) AND ([Extent3].[CustPartNum] IS NULL))

PartsRouting Table has 100,000+ records, Parts = 15000+, Processes = 200. PartsRou​​ting Table有100,000+条记录,Parts = 15000 +,Processs = 200。

I tried too many things found online but nothing worked for me as to how I can achieve the result with same performance of SQL. 我尝试了太多在网上找到的东西,但是对于如何以相同的SQL性能实现结果却没有任何帮助。

Based on the comments, looks like the issue is caused by the additional OR with IS NULL conditions in joins generated by the EF SQL translator. 根据注释,问题似乎是由EF SQL转换器生成的联接中带有IS NULL条件的附加OR引起的。 They were added in EF in order to emulate the C# == operator semantics which are different from SQL = for NULL values. 将它们添加到EF中是为了模拟C# ==运算符语义,该语义不同于SQL = NULL值。

You can start by turning that EF behavior off through UseDatabaseNullSemantics property (it's false by default): 您可以先通过UseDatabaseNullSemantics属性关闭该EF行为(默认情况下为false ):

WinCtx.Configuration.UseDatabaseNullSemantics = true;

Unfortunately that's not enough, because it fixes the normal comparison operators, but they simply forgot to do the same for join conditions. 不幸的是,这还不够,因为它修复了普通的比较运算符,但是他们只是忘记了对联接条件进行相同的操作。

In case you are using joins just for filtering (as it seems), you can replace them with LINQ Any conditions which translates to SQL EXISTS and nowadays database query optimizers are treating it the same way as if it was an inner join: 如果您仅将联接用于过滤(看起来),则可以将它们替换为LINQ。转换为SQL EXISTS Any条件,如今,数据库查询优化器都将其视为内部联接一样对待:

var query = (from r in WinCtx.PartsRoutings
             where WinCtx.Tab_Processes.Any(s => r.ProcessName == s.ProcessName)
             where WinCtx.Tab_Parts.Any(p => r.CustPartNum == p.CustPartNum)
             select new { r }).ToList();

You might also consider using just select r since creating anonymous type with single property just introdeces additional memory overhead with no advantages. 您可能还考虑仅使用select r因为使用单个属性创建匿名类型只会带来额外的内存开销,而没有任何优势。

Update: Looking at the latest comment, you do need fields from joined tables (that's why it's important to not omit relevant parts of the query in question). 更新:查看最新评论,您确实需要联接表中的字段(这就是为什么不忽略所查询的相关部分很重要)的原因。 In such case, you could try the alternative join syntax with where clauses: 在这种情况下,您可以尝试使用where子句的替代连接语法:

WinCtx.Configuration.UseDatabaseNullSemantics = true;
var query = (from r in WinCtx.PartsRoutings
             from s in WinCtx.Tab_Processes where r.ProcessName == s.ProcessName
             from p in WinCtx.Tab_Parts where r.CustPartNum == p.CustPartNum
             select new { r, s.Foo, p.Bar }).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM