SQL Server 2008 に 150 万件のレコードを含むテーブルがあります。索引付けされた varchar 列 'ReferenzNummer' があります。
SQL Management Studio で実行される次のクエリは機能し、高速です。
SELECT v1.Id, v2.Id FROM Vorpapier as v1 cross join Vorpapier as v2
WHERE v1.ReferenzNummer LIKE '7bd48e26-58d9-4c31-a755-a15500bce4c4'
AND v2.ReferenzNummer LIKE '7bd4%'
(クエリがこのようにあまり意味をなさないことはわかっています。さらに制約がありますが、それは今のところ重要ではありません)
ここで、Entity Framework 5.0 から次のようなクエリを実行したいと思います。私の LINQ は次のようになります。
var result = (from v1 in vorpapierRepository.DbSet
from v2 in vorpapierRepository.DbSet
where v1.ReferenzNummer == "7bd48e26-58d9-4c31-a755-a15500bce4c4" &&
v2.ReferenzNummer.StartsWith("7bd4")
select new { V1 = v1.Id, V2 = v2.Id })
.Take(10)
.ToList();
これは、テーブル全体をメモリにロードしようとするため、しばらくすると OutOfMemoryException が発生します。WHERE パーツを移動しようとしましたが、成功しませんでした:
var result = (from v1 in vorpapierRepository.DbSet.Where(v => v.ReferenzNummer == "7bd48e26-58d9-4c31-a755-a15500bce4c4")
from v2 in vorpapierRepository.DbSet.Where(v => v.ReferenzNummer.StartsWith("7bd4"))
select new { V1 = v1.Id, V2 = v2.Id })
.Take(10)
.ToList();
私が自分で書いたようなクロス結合ステートメントを作成するように Entity Framework に指示することは可能ですか?
更新 1
EF によって生成された SQL は次のようになります (両方のクエリに対して)
SELECT [Extent1].[Id] AS [Id],
[Extent1].[VorpapierArtId] AS [VorpapierArtId],
[Extent1].[ReferenzNummer] AS [ReferenzNummer],
[Extent1].[IsImported] AS [IsImported],
[Extent1].[DwhVorpapierId] AS [DwhVorpapierId],
[Extent1].[Datenbasis_Id] AS [Datenbasis_Id]
FROM [dbo].[Vorpapier] AS [Extent1]
更新 2
LINQ クエリを変更し、フィールド DatenbasisIDd でテーブル自体を結合すると (これは正確には必要ではありませんが、機能する可能性があります)、EF は結合を作成します。
var result = (from v1 in vorpapierRepository.DbSet
join v2 in vorpapierRepository.DbSet
on v1.DatenbasisId equals v2.DatenbasisId
where v1.ReferenzNummer == "7bd48e26-58d9-4c31-a755-a15500bce4c4" && v2.ReferenzNummer.StartsWith("7bd4")
select new { V1 = v1.Id, V2 = v2.Id })
.Take(10)
.ToList();
結果の SQL クエリは次のようになります。それは動作し、十分に高速です。
SELECT TOP (10) 1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent2].[Id] AS [Id1]
FROM [dbo].[Vorpapier] AS [Extent1]
INNER JOIN [dbo].[Vorpapier] AS [Extent2]
ON ([Extent1].[Datenbasis_Id] = [Extent2].[Datenbasis_Id])
OR (([Extent1].[Datenbasis_Id] IS NULL)
AND ([Extent2].[Datenbasis_Id] IS NULL))
WHERE (N'7bd48e26-58d9-4c31-a755-a15500bce4c4' = [Extent1].[ReferenzNummer])
AND ([Extent2].[ReferenzNummer] LIKE N'7bd4%')
元のクエリで EF がクロス結合を作成しない理由はまだわかりません。単にサポートされていないのですか?