如何在LINQ子查询中处理Null?

时间:2009-05-24 22:19:50

标签: vb.net linq linq-to-sql null

我有一个子查询,它返回子表中的最新值。在某些情况下,子查询不返回任何内容。下面的查询在运行时失败,因为MemberPrice的推断类型是十进制且不可为空。

简化查询:

Dim q = From s In dc.STOCKs _
        Select s.ID, MemberPrice = _
          (From mp In dc.STOCKPRICEs Where mp.NUMBER = s.NUMBER _
          Order By dc.date Descending _
          Select mp.PRICE).FirstOrDefault

在SQL中,子查询将包含Top(1),并在空时返回Null。我怎样才能在LINQ中处理这个问题?有没有办法让MemberPrice可以为空,或者如果找不到则将值默认为零(或更优雅的解决方案)?

非常感谢,Stuart

4 个答案:

答案 0 :(得分:6)

司徒,

我将数据库中的Price字段更改为不允许空值,并且我得到了同样的错误:

"Operator '??' cannot be applied to operands of type 'decimal' and 'int'". 

正如您所指出的,当Price设置为不允许数据库中的空值时,空合并运算符不再起作用,因为它期望看到可为空的十进制类型:

decimal?

如果我删除空合并运算符并运行不包含价格的测试用例,我会得到:

"The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type.."

这是有效的代码。我将子查询结果转换为十进制?在应用空合并运算符之前。

public class Class1
{

    DataClasses1DataContext dc = new DataClasses1DataContext();

    public decimal test(int stockID)
    {

        var q = from s in dc.Stocks
                where s.StockID == stockID
                select new
                {
                    StockID = s.StockID,
                    memberPrice = ((decimal?)(from mp in dc.StockPrices
                                   where mp.StockID == s.StockID
                                   select mp.Price).FirstOrDefault()) ?? 0
                };

        return q.FirstOrDefault().memberPrice;
    }
}

答案 1 :(得分:3)

斯图尔特,试试这个:

Dim q = From s In dc.STOCKs _
    Select s.ID, MemberPrice = _
      if((From mp In dc.STOCKPRICEs Where mp.NUMBER = s.NUMBER _
      Order By dc.date Descending _
      Select mp.PRICE).FirstOrDefault),0)

null合并运算符会将MemberPrice的null值强制为零。

答案 2 :(得分:0)

DefaultIfEmpty扩展方法是否可以执行您要查找的内容?

答案 3 :(得分:0)

斯图尔特,

这就是我在机器上工作的方式。我为它在c#中道歉;自从我使用VB以来已经太久了。

注意在“select”语句中使用“new”运算符,并在FirstOrDefault()之后使用null coalescing运算符。

public class Class1
{

    DataClasses1DataContext dc = new DataClasses1DataContext();

    public decimal MemberPrice(int stockID)
    {

        var q = from s in dc.Stocks
                where s.StockID == stockID
                select new
                {
                    StockID = s.StockID,
                    memberPrice = (from mp in dc.StockPrices
                                   where mp.StockID == s.StockID
                                   select mp.Price).FirstOrDefault() ?? 0
                };

        return q.FirstOrDefault().memberPrice;
    }
}