Null coalesce在LINQ查询中不起作用

时间:2012-07-21 17:18:59

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

拿这个:

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。

1 个答案:

答案 0 :(得分:5)

在SQL中,NULL不等于NULL。

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

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

更新:

条件

([Extent5].[MediaCategoryFormatID] = [Extent5].[MediaCategoryFormatID]) 
当[Extent5]时,

确实会返回false。[MediaCategoryFormatID]为NULL。

这回答了“为什么没有返回任何东西?”的问题。

然而,另一个问题浮现在脑海中:为什么实体框架会从这个linq查询生成SQL?

我担心实体的linq并不完全以其SQL生成的质量而闻名,这种情况似乎证实了这一点。你可能会考虑Linq to SQL。即使从长远来看这似乎是一条死路,但目前的实施情况如果要比实体更好。

在任何一种情况下,你有没有试过像

这样的东西
someObjectList.Where(x => 
    !item1.hasValue || 
    x.SomeItem1.HasValue && x.SomeItem1.Value == item1.Value)

请确保在分析器下验证,但实体中的linq也可能会搞乱它。