Linq到SQL左连接左连接/一条Linq到SQL语句中的多个左连接

Linq到SQL左连接左连接/一条Linq到SQL语句中的多个左连接,linq,linq-to-sql,stored-procedures,left-join,Linq,Linq To Sql,Stored Procedures,Left Join,我正在尝试将SQL过程重写为Linq,只要它能在小数据集上工作,一切都很顺利。我在任何地方都找不到答案。问题是,我在查询中有3个连接,2个是左连接,1个是内部连接,它们彼此连接/就像一棵树一样。下面您可以看到SQL过程: SELECT ... FROM sprawa s (NOLOCK) LEFT JOIN strona st (NOLOCK) on s.ident = st.id_sprawy INNER JOIN stan_szczegoly ss

我正在尝试将SQL过程重写为Linq,只要它能在小数据集上工作,一切都很顺利。我在任何地方都找不到答案。问题是,我在查询中有3个连接,2个是
左连接
,1个是
内部连接
,它们彼此连接/就像一棵树一样。下面您可以看到SQL过程:

SELECT ...
    FROM sprawa s (NOLOCK) 
        LEFT JOIN strona st (NOLOCK) on s.ident = st.id_sprawy
        INNER JOIN stan_szczegoly ss (NOLOCK) on s.kod_stanu = ss.kod_stanu
        LEFT JOIN broni b (NOLOCK) on b.id_strony = st.ident
我想问你的是一种把这个翻译成Linq的方法。现在我有这个:

var queryOne = from s in db.sprawa
               join st in db.strona on s.ident equals st.id_sprawy into tmp1
               from st2 in tmp1.DefaultIfEmpty()
               join ss in db.stan_szczegoly on s.kod_stanu equals ss.kod_stanu
               join b in db.broni on st2.ident equals b.id_strony into tmp2
               from b2 in tmp2.DefaultIfEmpty()
               select new { };
看起来还可以,但当使用SQL Profiler检查时,发送到数据库的查询如下所示:

SELECT ... FROM    [dbo].[sprawa] AS [Extent1] 
           LEFT OUTER JOIN [dbo].[strona] AS [Extent2] 
                ON [Extent1].[ident] = [Extent2].[id_sprawy]    
           INNER JOIN [dbo].[stan_szczegoly] AS [Extent3] 
                ON [Extent1].[kod_stanu] = [Extent3].[kod_stanu]    
           INNER JOIN [dbo].[broni] AS [Extent4] 
                ON ([Extent2].[ident] = [Extent4].[id_strony]) OR 
                (([Extent2].[ident] IS NULL) AND ([Extent4].[id_strony] IS NULL))
正如您所看到的,这两个SQL查询略有不同。效果是一样的,但后者的工作速度要慢得无法比拟(不到一秒到超过30分钟)。还有一个
联合体
,但这不应该是问题所在。如果要求,我会粘贴它的代码


如果您能就如何提高Linq语句的性能或如何以正确翻译的方式编写Linq语句提供任何建议,我将不胜感激。

我想我找到了解决方案:

var queryOne = from s in db.sprawa
               join st in db.strona on s.ident equals st.id_sprawy into tmp1
               where tmp1.Any()
               from st2 in tmp1.DefaultIfEmpty()
               join ss in db.stan_szczegoly on s.kod_stanu equals ss.kod_stanu
               join b in db.broni on st2.ident equals b.id_strony into tmp2
               where tmp2.Any()
               from b2 in tmp2.DefaultIfEmpty()
               select new { };
换句话说,
where table.Any()
在每个
语句之后进入table
语句。它并没有使翻译变得更好,但已经将执行时间从近30分钟(!)加快到大约5秒


但必须小心使用,因为这可能会导致结果集中的一些记录丢失。

如果zakreslenie是一个变量,您可以使用“If(zakreslenie==-1)then{}else{}”将语句分解为两个不同的语句。或语句往往对性能不利,因此可能会有所帮助。如果您真的无法将复杂的linq语句转换为性能良好的查询,那么也许值得考虑调用存储过程,因为糟糕的存储过程也不能很好地工作。另外,正如我前面所说的,问题在于连接,其他一切都可以正常工作(修改翻译后的sql查询),如果您不能进行快速sql查询来完成您想要的任务,那么您也将无法进行快速linq语句。不过,优化slq查询以提高速度要比优化linq语句容易得多,因为使用sql,您可以得到一个解释计划来找出是什么让它慢下来的。可能是查询中的OR导致了速度下降,但也可能是缺少适当的索引。我已经告诉过你问题所在,就是查询如何翻译,我已经尝试过在没有“OR”的情况下编写它,我也有相当快的SQL查询,但过滤速度仍然太慢(对于小数据集,该方法的运行速度要快6倍,但对于大数据集,该方法的运行速度会变慢)。我已经在查询中使用的dbo.sprawa中的所有字段上设置了索引,在联接中使用的所有字段上的索引都没有提高一点速度。一般来说,根据我的经验,SQL server在
子句方面多次表现不佳。但实体框架设计者似乎没有意识到这一点。这没有任何意义。如果您强制tmp1和tmp2有任何记录要限定,那么您就有一个联接,而不是左联接。好吧,它完成了它的工作,查询以相同的方式工作,而且速度更快。我不确定,但我认为tmp.any()不会强制任何记录限定,它将限定存在的记录。是否要我向您显示SQL查询的结果?