null vs default(decimal?)设置为null - 给出不同的结果

时间:2016-05-10 15:55:18

标签: c# linq entity-framework-4 linq-to-entities

  

使用:Entity Framework 4.3.1,MVC 4

示例数据库记录(例如):

Id    Height
1     null  
2     2.1

为什么第一个陈述会带来零结果:

decimal? scannedItemHeight = default(decimal?);

(from st in Stocks
 where st.Height == scannedItemHeight 
 select st.Id).ToList();

但是此语句返回记录Id 1:

(from st in Stocks
 where st.Height == null
 select st.Id).ToList();

如果scanningItemHeight为null,我只想匹配高度为null的值。

我只想返回第一条记录,Id 1。

更新 我最终使用了:

st.Height == scannedItemHeight || (scannedItemHeight == null && st.Height == null)

2 个答案:

答案 0 :(得分:3)

我之前确实看到过一些奇怪的LINQ行为,因为SQL处理空值的方式与C#处理空值的方式不同。在C#中,如果a == ba都为空,则b为真,而在SQL中,它们不是......而是您必须故意检查无效。我会尝试:

var temp = (from st in Stocks
            where st.Height == scannedItemHeight || (scannedItemHeight == null && st.Height == null)
            select st.Id).ToList();

或者以不同方式构建查询:

var filtered = scannedItemHeight == null
    ? Stocks.Where(st => st.Height == null)
    : Stocks.Where(st => st.Height == scannedItemHeight);
var temp = filtered.Select(st => st.Id).ToList();

答案 1 :(得分:3)

那是因为在第一种情况下数据库查询类似于

where Height = @param1 ...

而在第二种情况下将是

where Height is null

第一个查询将不返回任何结果,因为@param1将为null,并且没有行可以匹配此类条件。

要点是从C#的角度来看这些查询是等价的,但是从sql的角度看它们不是:你应该在sql中使用IS NULL(或IS NOT NULL)来检查空值。

如何修复取决于您的参数为null时要执行的操作。在您的情况下:使用Jon Skeet的回答

如果有人想要忽略参数而根本没有过滤(很常见的情况,例如当参数代表用户在某些字段中的输入时,当没有任何内容输入时 - 没有任何可过滤的内容),那么做:

where scannedItemHeight == null || st.Height == scannedItemHeight

将在sql中,如

where @param1 is null OR Height = @param1