【问题标题】:Conditional Joins in LINQLINQ 中的条件连接
【发布时间】:2010-11-29 23:41:10
【问题描述】:

我有一个父子表关系。在下面的示例中,Foo 有一个 FooID 和一个指向父记录的可为空的 ParentFooID。

Bar 表始终链接到父记录。这是我用来获取结果的 SQL。

Select * from Foo f
JOIN  Bar b
  ON b.FooID =  
     CASE 
       WHEN f.ParentFooID is null
         THEN f.FooID
       ELSE f.ParentFooID
     END

我在将其输入 LINQ 查询时遇到了一些麻烦。我想避免像下面这样的交叉连接:

    var q = from f in Foo 
            from b in Bar 
            where  b.FooID == (f.ParentFooID ?? f.FooID)

干杯,

丹尼尔

【问题讨论】:

    标签: c# .net linq-to-sql join conditional


    【解决方案1】:

    您的具体示例是使用CASE 回退到一个非空值,这实际上只是一个COALESCE。在这种情况下,这是可行的:

    var q = from f in dc.Foos
            join
            b in dc.Bars
            on
            (f.ParentFooID ?? f.FooID)
            equals
            b.FooID
            into grouped
            select grouped;
    

    翻译成:

    SELECT ...
    FROM [dbo].[Foo] AS [t0]
    LEFT OUTER JOIN [dbo].[Bar] AS [t1]
    ON (COALESCE([t0].[ParentFooID],[t0].[FooID])) = [t1].[FooID]
    ORDER BY [t0].[FooID], [t1].[BarID]
    

    关键是COALESCE(case1, case2) 上的左外连接,所以表达式转换器似乎确实理解这一点。

    【讨论】:

      【解决方案2】:

      不直接回答您的问题,但如果没有条件条件,原始查询不会更好地表述为:

      Select * 
      from Foo f
      JOIN Bar b ON b.FooID = f.FooID
      Where f.ParentFooID is null
      UNION ALL
      Select * 
      from Foo f
      JOIN Bar b ON b.FooID = f.ParentFooID
      Where f.ParentFooID is not null
      

      在哪种情况下,LINQ 表达式应该更简单?

      【讨论】:

        【解决方案3】:

        一些复杂的场景没有被 LINQ 很好地映射;我建议加入case 就是其中之一。重新将其作为交叉连接进行...您对其进行了分析吗? (即来自from ... from ... (LINQ) 与复杂的join (TSQL) 的后续 SQL?在许多情况下,分析器可以从旧式方法获得相同(或相似)的查询计划。

        【讨论】:

        • 我已经分析了 from...from 场景,是的,它确实会导致交叉连接,它会执行索引扫描(而不是搜索),所以它的性能会比原来的差很多正在执行索引查找的查询。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        相关资源
        最近更新 更多