Linq到SQL左连接左连接/一条Linq到SQL语句中的多个左连接
我正在尝试将SQL过程重写为Linq,只要它能在小数据集上工作,一切都很顺利。我在任何地方都找不到答案。问题是,我在查询中有3个连接,2个是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
左连接
,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查询的结果?