【问题标题】:Null coalesce not working in LINQ queryNull 合并在 LINQ 查询中不起作用
【发布时间】:2012-07-21 17:18:58
【问题描述】:

拿着这个:

int? item1 = null;
int? item2 = null;

someObjectList.Where(x => x.SomeItem1 == (item1 ?? x.SomeItem1)
                       && x.SomeItem2 == (item2 ?? x.SomeItem2) 
                    );

其中someObjectList 不为空且SomeItem1SomeItem2 在列表中的所有对象中为null

为什么什么都不返回?

编辑:

我的代码:

public void GetPlacementsByMaterial(long clientMaterialID)
{
    ClientMaterial clientMaterial = ((ApplicationEntityModel)NavigationItem.ObjectContext).ClientMaterial.FirstOrDefault(x => x.ClientMaterialID == clientMaterialID);

    var list = GetPlacementList(supplier, mediaSpace);

    PlacementsList = list.Where(x => x.MediaCategoryFormatID == (clientMaterial.MediaCategoryFormatID ?? x.MediaCategoryFormatID)
                                                && x.MediaCategorySizeID == (clientMaterial.MediaCategorySizeID ?? x.MediaCategorySizeID) 
                             );
}

所有 ID 均为 Nullable<long>

编辑:

SQL 探查器:

SELECT *
  FROM [dbo].[CampaignSchedulePlacements] AS [Extent5]
WHERE ([Extent5].[MediaCategoryFormatID] = [Extent5].[MediaCategoryFormatID]) AND ([Extent5].[MediaCategorySizeID] = [Extent5].[MediaCategorySizeID])

注意:清理了`SQL。

【问题讨论】:

  • 请发布重现问题的完整示例。
  • 它对我来说很好用。 SomeItem1 的类型是什么?它是否有一个重载的== 运算符?
  • list 的类型是什么?你使用的是 Linq-To-Objects,还是一些 IQueryable 的东西?
  • @CodesInChaos 使用 Linq-to-entities,这都是基本查询。没有什么花哨。所有对象都是EntityObject 类型。我只是似乎无法解决...
  • 您正在使用 Linq to Entities。查看使用调试器(例如在 Intellitrace 中)生成的实际 SQL。

标签: c# .net linq linq-to-entities entity-framework-4.3


【解决方案1】:

在 SQL 中,NULL 不等于 NULL。

您可以将 NULL 解释为:“有价值,但我不知道它是什么”。因此,如果您要比较两个 NULL 值,您实际上是在问“第一个未知值是否等于第二个未知值?”当然,没有理由假设它们是,所以 SQL 会说“不”。

我假设这是导致您的问题的原因。您可以通过查看生成的实际 SQL 来验证这一点。如果它使用 SQL = 运算符,这确实是问题所在。如果您使用的是 SQL Server,您可以通过在数据库工具(例如 SQL Management Studio)中运行 SQL 来验证这一点。

更新:

条件

([Extent5].[MediaCategoryFormatID] = [Extent5].[MediaCategoryFormatID]) 

当 [Extent5].[MediaCategoryFormatID] 为 NULL 时,确实会返回 false。

这回答了“为什么它什么都不返回?”的问题

但是,我想到了另一个问题:为什么实体框架会从这个 linq 查询中生成那个 SQL?

恐怕 linq to entity 并不完全以其 SQL 生成的质量而闻名,而这个案例似乎证实了这一点。您可能会考虑使用 Linq to SQL。即使从长远来看,这似乎是一条死胡同,但当前的实现如果比 linq to entity 好得多。

无论哪种情况,您都尝试过类似的方法

someObjectList.Where(x => 
    !item1.hasValue || 
    x.SomeItem1.HasValue && x.SomeItem1.Value == item1.Value)

确保在分析器下也验证一下,linq to entity 也可能会搞砸。

【讨论】:

  • 请看我的更新。我在SQL Profiler 上运行它。还有其他想法吗?
  • 谢谢克里斯。排序。在== 的两边是NULL
  • @Willem 和 Kris:这种行为实际上是 LINQ to Entities 中的一个旧错误:stackoverflow.com/questions/682429/… null == null 在 .NET 中是 true,因此不能直接将其转换为 NULL = NULL在不是 true 的 SQL 中。它已针对 .NET 4.5 进行了修复,因此您不再需要上述解决方法以及 .NET 4.5 中链接问题的答案。
  • @Slauma 感谢您的链接。 +1
猜你喜欢
  • 2017-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-31
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多