【问题标题】:optimize Entity Framework Linq query (selected 1 unexpected field)优化 Entity Framework Linq 查询(选择 1 个意外字段)
【发布时间】:2015-10-15 08:40:00
【问题描述】:

全部,

谁能帮我优化以下 EF/Linq 查询:

EF/Linq 查询(取自 LinqPad):

Articles
    .AsNoTracking()
    .Where(a => a.Active == "J")
    .SelectMany(a => KerlServices
        .Where(ks => ks.Service.SAPProductNumber == a.SAPProductNumber))
    .Select(ks => new {
        ks.KerlCode,
        ks.Service.SAPProductNumber,
        ks.Service.Type })
    .ToList()

Articles 和 Services (ks.Service.SAPProductNumber == a.SAPProductNumber) 之间的关系理论上是 1:optional 关系 with 不能在 EF 中定义。然而,这不是我的问题。

生成的 SQL 查询:

SELECT 
    [Join1].[F_SERVICESID] AS [F_SERVICESID], 
    [Join1].[F_KERLCOD] AS [F_KERLCOD], 
    [Join1].[F_SAPARTNUM] AS [F_SAPARTNUM], 
    [Join1].[F_TYPE] AS [F_TYPE]
    FROM  [dbo].[T_ART] AS [Extent1]
    INNER JOIN  (SELECT [Extent2].[F_KERLCOD] AS [F_KERLCOD], [Extent2].[F_SERVICESID] AS [F_SERVICESID], [Extent3].[F_SAPARTNUM] AS [F_SAPARTNUM], [Extent3].[F_TYPE] AS [F_TYPE]
        FROM  [dbo].[T_SERVICESKERL] AS [Extent2]
        INNER JOIN [dbo].[T_SERVICES] AS [Extent3] ON [Extent2].[F_SERVICESID] = [Extent3].[F_ID] ) AS [Join1] ON [Extent1].[F_SAPARTNUM] = [Join1].[F_SAPARTNUM]
    WHERE N'J' = [Extent1].[F_ACTIND]

为什么 EF 会生成选择 [Join1].[F_SERVICESID] 的查询?我不需要这个字段。有谁知道防止这种情况的方法吗?

亲切的问候,简。

附加 1:

KerlServices
    .AsNoTracking()
    .Select(ks => new {
        ks.KerlCode,
        ks.Service.SAPProductNumber,
        ks.Service.Type })
    .Join(
        Articles,
        ks => ks.SAPProductNumber,
        a => a.SAPProductNumber,
        (ks, a) => new { ks, a.Active })
    .Where(ksa => ksa.Active == "J")
    .Select(ksa => ksa.ks)
    .ToList()

结果:

SELECT 
    [Extent1].[F_SERVICESID] AS [F_SERVICESID], 
    [Extent1].[F_KERLCOD] AS [F_KERLCOD], 
    [Extent2].[F_SAPARTNUM] AS [F_SAPARTNUM], 
    [Extent2].[F_TYPE] AS [F_TYPE]
    FROM   [dbo].[T_SERVICESKERL] AS [Extent1]
    INNER JOIN [dbo].[T_SERVICES] AS [Extent2] ON [Extent1].[F_SERVICESID] = [Extent2].[F_ID]
    INNER JOIN [dbo].[T_ART] AS [Extent3] ON [Extent2].[F_SAPARTNUM] = [Extent3].[F_SAPARTNUM]
    WHERE N'J' = [Extent3].[F_ACTIND]

这个“改进”没有回答我自己的问题,但结果对我来说肯定看起来更漂亮。

更新 1:

Ivan Stoev 的回答中的查询产生以下 SQL:

SELECT 
    [Extent1].[F_SERVICESID] AS [F_SERVICESID], 
    [Extent1].[F_KERLCOD] AS [F_KERLCOD], 
    [Extent2].[F_SAPARTNUM] AS [F_SAPARTNUM], 
    [Extent2].[F_TYPE] AS [F_TYPE]
    FROM  [dbo].[T_SERVICESKERL] AS [Extent1]
    INNER JOIN [dbo].[T_SERVICES] AS [Extent2] ON [Extent1].[F_SERVICESID] = [Extent2].[F_ID]
    WHERE  EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[T_ART] AS [Extent3]
        WHERE (N'J' = [Extent3].[F_ACTIND]) AND ([Extent3].[F_SAPARTNUM] = [Extent2].[F_SAPARTNUM])
    )

【问题讨论】:

  • 我的想法已经不多了。 EF版?数据库类型 - Sql Server?您是否在 VS 而不是 LinqPad 中检查过它?
  • @IvanStoev:看看在不使用 LinqPad 时生成了什么 SQL 是个好主意。也许是 LinqPad 负责。
  • 查看我的更新答案。我在处理另一个 SO 问题时发现了类似的情况,从查询物化的角度来看完全没有问题。

标签: c# sql entity-framework linq query-optimization


【解决方案1】:

为什么 EF 会生成选择 [Join1].[F_SERVICESID] 的查询?我不需要这个字段。

如果是真的那很奇怪,我对此没有任何解释。

谁能帮我优化以下 EF/Linq 查询

值得尝试以下方法,这对我来说代表了检索相关数据的最合乎逻辑的方式:

KerlServices
    .AsNoTracking()
    .Select(ks => new {
        ks.KerlCode,
        ks.Service.SAPProductNumber,
        ks.Service.Type })
    .Where(ks => Articles.Any(a => a.Active == "J" && a.SAPProductNumber == ks.SAPProductNumber)
    .ToList()

更新: 最近我发现 EF 在使用外键关系拨号时在生成的 SQL 查询中包含一些附加字段。这些字段包含在投影结果中,所以我认为您不必担心。采取上述任何查询,在真实代码环境(VS 调试)中执行它并检查投影列表 - 我很确定相关字段不会存在。

【讨论】:

  • 感谢您的回答。太酷了,您实际上提到了我在开始优化之前的 exact 查询。我将生成的 SQL 作为 UPDATE 1 添加到我原来的问题中。
  • @JanC.deGraaf Sql 查询看起来和我手写的完全一样,当然除了别名和那个奇怪的列。所以无论我们做什么,你都会得到[F_SERVICEID]。顺便说一句,KerlCode 属性的类型是什么?
  • KerlCode 属性的类型是 required-string-length-5。在数据库中是nvarchar(5), not null
  • 而且,是的,EF 经常(总是?)似乎将 FK 字段添加到选择列表中。
  • 您是正确的,这些额外的字段不包含在投影结果中,但是这些额外的列被选择并从 DB-server 传输到 EF-client,消耗宝贵的带宽。
猜你喜欢
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2020-07-18
  • 1970-01-01
相关资源
最近更新 更多