【问题标题】:Simple Linq expression producing bloated where clause that doesn't make sense to me简单的 Linq 表达式产生臃肿的 where 子句,这对我来说没有意义
【发布时间】:2016-03-04 20:48:57
【问题描述】:

我正在尝试使用这个 Linq 表达式

Dim ex2 As Expression(Of Func(Of Advertisement, Boolean)) =
    Function(a) a.Address.CountryCode = ISO AndAlso a.Address.Region = EmptyString

这样

Dim ltest = (From a In db.Advertisements.AsExpandable().Where(ex2)).ToList

但它会产生这些疯狂的条件

DECLARE @p__linq__0 NVARCHAR (MAX) = N'US';
DECLARE @p__linq__1 NVARCHAR (MAX) = N'';
SELECT [Extent1].[AdvertisementID] AS [AdvertisementID],
       [Extent1].[URL] AS [URL],
       [Extent1].[Address_AddressID] AS [Address_AddressID],
       [Extent1].[Business_BusinessID] AS [Business_BusinessID]
FROM [dbo].[Advertisements] AS [Extent1]
LEFT OUTER JOIN [dbo].[Addresses] AS [Extent2]
             ON [Extent1].[Address_AddressID] = [Extent2].[AddressID]
WHERE (([Extent2].[CountryCode] = @p__linq__0)
       OR (([Extent2].[CountryCode] IS NULL)
           AND (@p__linq__0 IS NULL)))
  AND (([Extent2].[Region] = @p__linq__1)
       OR (([Extent2].[Region] IS NULL)
           AND (@p__linq__1 IS NULL)))

当我的参数是字符串而不是可空值时,我不知道为什么它会产生@p__linq__1 IS NULL

我希望它会产生类似的东西

WHERE [Extent2].[CountryCode] = @p__linq__0 AND [Extent2].[Region] = @p__linq__1

我使用 LinqKit 谓词而不是表达式尝试了同样的事情,但得到了相同的结果。实际上,我有一个更复杂的查询,带有额外的 where 子句,但是当它不起作用时,我将其分解为这个简单的查询,发现 where 子句与我的预期完全不同。

所以问题是生成类似于我使用 LinqKit 表达式或谓词的更简单的 where 子句的正确方法是什么?

【问题讨论】:

  • 数据库中的 Advertisements.CountryCode 字段是否可以为空?
  • Advertisements.Address_AddressID 可能为空,尽管 Addresses.CountryCode 不为空。但是,如果我的字符串 @p__linq__0 不能为空,那么当它永远不可能为真时,为什么还要在查询中包含它呢?为什么不直接省略这些重复片段 OR (([Extent2].[CountryCode] IS NULL) AND (@p__linq__0 IS NULL))
  • “我的参数是字符串而不是可以为空的”——但字符串是引用类型——它们本质上是可以为空的。
  • 是否有类似于我可以使用的不能为 null 的字符串的东西可能会删除额外的 sql?在调试 SQL 时,我必须先删除多余的项目,然后才能理解发生了什么。您可以提出任何有助于简化它的建议。

标签: sql vb.net entity-framework linq linqkit


【解决方案1】:

是否有类似于我可以使用的不能为 null 的字符串的东西,它可能会删除额外的 sql?

您可以尝试在表达式中添加保证字符串不为空的要求:

a.Address.CountryCode = ISO _
    AndAlso Not EmptyString Is Nothing _
    AndAlso a.Address.Region = EmptyString

但是,EF 生成的 SQL 旨在准确表示传入的表达式(包括 null 语义的差异),不一定要完全优化或人类可读。这意味着 SQL 生成器可能无法通过添加该要求生成您期望的 exact sql。

或者,如果EmptyString 是一个“常量”值,实际上是一个空字符串,您可以尝试改用String.Empty。解释器可以在查询中使用常量值而不是使用参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-24
    • 2019-09-23
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 2021-12-25
    相关资源
    最近更新 更多