【问题标题】:Entity framework: cross join causes OutOfMemoryException实体框架:交叉连接导致 OutOfMemoryException
【发布时间】:2013-01-19 09:43:45
【问题描述】:

我在 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 不在原始查询中创建交叉联接。是根本不支持吗?

【问题讨论】:

  • 您必须展示您的VorpapierRepository 实现。我假设存储库实现中存在问题,因为您的 LINQ 看起来是正确的。
  • @hamlet-hakobyan:vorpapierRepository 返回 EF DbSet。因此,该存储库的实现应该无关紧要。
  • @delixfe 你只能假设。
  • vorpapierRepository.DbSet 是一个 EF IDbSet,出于测试目的,我暂时添加了它。
  • 生成什么SQL?它是否包含谓词?

标签: entity-framework cross-join


【解决方案1】:

如果您在 linq 语句中使用连接,它将被传递回 SQL Server。以下是 linq 中连接运算符的一些示例:http://code.msdn.microsoft.com/LINQ-Join-Operators-dabef4e9

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多