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

发布于 2024-07-20 12:31:23 字数 487 浏览 5 评论 0原文

我有一个子查询,它返回子表中的最新值。 在某些情况下,子查询不返回任何内容。 下面的查询在运行时失败,因为 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 可以为空或如果找不到则将值默认为零(或更优雅的解决方案)?

非常感谢,斯图尔特

I've got a subquery that returns the most recent value from a child table. In some cases the subquery returns nothing. The query below fails at runtime because the inferred type of MemberPrice is decimal and is not nullable.

Simplified query:

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

In SQL, the subquery would contain Top (1) and would return Null when empty. How can I handle this in LINQ? Is there a way to make MemberPrice nullable or default the value to zero if not found (or a more elegant solution)?

Many thanks, Stuart

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

忱杏 2024-07-27 12:31:23

Stuart,

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

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

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

decimal?

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

"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;
    }
}

Stuart,

I changed my Price field in the database to not allow nulls, and I got the same errror you did:

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

As you pointed out, when Price is set to not allow nulls in the database, the null coalescing operator no longer works because it is expecting to see a nullable type decimal:

decimal?

If I remove the null coalescing operator and run the test case that doesn't contain a price, I get:

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

Here is the code that works. I cast the subquery result to decimal? before applying the null coalescing operator.

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;
    }
}
难理解 2024-07-27 12:31:23

Stuart,试试这个:

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)

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

Stuart, try this:

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)

The null coalescing operator will coerce the null value to zero for MemberPrice.

画中仙 2024-07-27 12:31:23

DefaultIfEmpty 扩展方法是否可以满足您的需求?

Does the DefaultIfEmpty extension method do what you're looking for?

踏月而来 2024-07-27 12:31:23

斯图尔特,

这就是我让它在我的机器上工作的方法。 对于它是用 c# 编写的,我深表歉意; 好久没用VB了。

请注意“select”语句中“new”运算符的使用,以及 FirstOrDefault() 之后空合并运算符的使用。

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;
    }
}

Stuart,

This is how I got it to work on my machine. I apologize for it being in c#; it's been too long since I've used VB.

Note the use of the "new" operator in the "select" statement, and the use of the null coalescing operator after the FirstOrDefault().

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文