2017-12-12 15 views
2

次のlinq文(.net 4.5)では、2つのテーブルに対して左ジョインを行い、次に各ジョインの最初のローを取ろうとしていますソートは2番目のテーブルで行われます。 Wantedカラムは常に、データベース内の最初の列から値を返すようOrderByDescendingコールが、第二のテーブルに適用されていないがサブクエリ、内部Selectを選択しないで基になるクエリにOrder By

using (var context = new TestEntities()) 
{ 
    var items = ctx.FirstTables 
        .GroupJoin(
         ctx.SecondTables, 
         first => first.IntJoin, 
         second => second.IntJoin, 
         (firstTableRow, secondTableRows) 
          => new { firstTableRow, secondTableRows }) 
        .Select(
         result => new 
            { 
             result.firstTableRow.IntJoin, 
             NewWanted = result.secondTableRows 
                 .OrderByDescending(x => x.Sort) 
                 .Select(x => (int?)x.Wanted) 
                 .DefaultIfEmpty(null) 
                 .FirstOrDefault() 
            }); 
} 

。私は、以下のリストを取得することが期待でしょう

IntJoin || Sort || Wanted 
0   0  1 
0   1  2 
0   2  3 
1   0  6 
1   1  5 
1   2  4 
null  0  7 
null  1  9 
null  2  8 

IntJoin || NewWanted 
0   3 
1   4 
2   null 
null  8 

IntJoin 
0 
1 
2 
null 

SecondTable:

だから次の表は、

FirstTable値与えられましたしかし私は、この

IntJoin || NewWanted 
0   1 
1   6 
2   null 
null  7 

で取得し、OrderByDescendingコールとEntity FrameworkのコアISNを無視している.NET Frameworkの.NETのコアに2.0.1

IntJoin || NewWanted 
0   3 
1   4 
2   null 
null  null 

だから、Entity Frameworkの実行EntityFrameworkCoreに次のように取得します't(.net Coreはnull比較を処理できないようです。私はコアを使用していないだけの問題は、他の質問に残されている(または別の質問に答えられるかもしれない)ので、差をテストするための例を作成しました

私はこのすべてを試してみました。 Entity Framework 6.2.0を使用して)、.NET Core 2.0(Entity Framework Core 2.0.1を使用)をMicrosoft Sql Server 2008および2016で使用し、同じ結果を達成しました。

私はおそらくGroupJoinSelect.ToList()を呼び出すことができます知っているが、これは大きなクエリの一部であり、メモリ内のクエリを実行することは非常に高額になります。

私も

答えて

2

あなたはEF6クエリの翻訳(EFコアに比べて少数の1)にヒットしましたように見えるに違いなしSelectSort列を含む、OrderByを呼び出すだけでなく、異なる値を試してみました

SELECT 
    1 AS [C1], 
    [Project3].[IntJoin] AS [IntJoin], 
    [Project3].[C1] AS [C2] 
    FROM (SELECT 
     [Extent1].[IntJoin] AS [IntJoin], 
     (SELECT TOP (1) 
      [Project1].[Wanted] AS [Wanted] 
      FROM (SELECT 1 AS X) AS [SingleRowTable1] 
      LEFT OUTER JOIN (SELECT 
       [Extent2].[Wanted] AS [Wanted] 
       FROM [dbo].[SecondTable] AS [Extent2] 
       WHERE ([Extent1].[IntJoin] = [Extent2].[IntJoin]) OR (([Extent1].[IntJoin] IS NULL) AND ([Extent2].[IntJoin] IS NULL))) AS [Project1] ON 1 = 1) AS [C1] 
     FROM [dbo].[FirstTable] AS [Extent1] 
    ) AS [Project3] 

ソリューションはDefaultIfEmptyOrderByDescending前に(基本的には「通常」のLINQは左外部結合パターン以下移動することです:

生成されたSQLクエリからのバグには ORDER BY句を持っていません

SELECT 
    1 AS [C1], 
    [Extent1].[IntJoin] AS [IntJoin], 
    [Limit1].[Wanted] AS [Wanted] 
    FROM [dbo].[FirstTable] AS [Extent1] 
    OUTER APPLY (SELECT TOP (1) [Project2].[Wanted] AS [Wanted] 
     FROM (SELECT 
      [Project1].[Sort] AS [Sort], 
      [Project1].[Wanted] AS [Wanted] 
      FROM (SELECT 1 AS X) AS [SingleRowTable1] 
      LEFT OUTER JOIN (SELECT 
       [Extent2].[Sort] AS [Sort], 
       [Extent2].[Wanted] AS [Wanted] 
       FROM [dbo].[SecondTable] AS [Extent2] 
       WHERE ([Extent1].[IntJoin] = [Extent2].[IntJoin]) OR (([Extent1].[IntJoin] IS NULL) AND ([Extent2].[IntJoin] IS NULL))) AS [Project1] ON 1 = 1 
     ) AS [Project2] 
     ORDER BY [Project2].[Sort] DESC) AS [Limit1] 

および所望の結果を生成する:に変換

NewWanted = result.secondTableRows 
       .DefaultIfEmpty() // <-- 
       .OrderByDescending(x => x.Sort) 
       .Select(x => (int?)x.Wanted) 
       //.DefaultIfEmpty() 
       .FirstOrDefault() 

関連する問題