【问题标题】:Why don't the values from my linq queries appear immediately?为什么我的 linq 查询中的值没有立即出现?
【发布时间】:2017-06-22 07:07:46
【问题描述】:

我有以下 linq 查询块来计算报告的一些值。

var items = (from trans in calclabordb.Sales_Transactions                
             select trans).SelectMany(st => st.Sales_TransactionLineItems).Where(stli => stli.TypeID == typeID);

decimal test = items.Where(stli => stli.Inventory_Item is Base).Sum(stli => (decimal?)stli.Inventory_Item.IntExtraServiceAmount) ?? 0;
decimal test2 = items.Where(stli => stli.Inventory_Item is Extra).Sum(stli => (decimal?)stli.ItemPrice) ?? 0;
decimal test3 = test + test2;
current.ExtraSales = items.Where(stli => stli.Inventory_Item is Base).Sum(stli => (decimal?)stli.Inventory_Item.IntExtraServiceAmount) ?? 0 +
    items.Where(stli => stli.Inventory_Item is Extra).Sum(stli => (decimal?)stli.ItemPrice) ?? 0;

我在调试器中单步执行了代码,发现了一些奇怪的地方。分配到test 后,其值为0。分配到test2 test2 == 0test == 11.31 后分配到test3 test == 11.31 test2 == 11.28test3 == 22.59 后分配到ExtraSales ExtraSales == 11.31。当这一切都完成时,ExtraSales 中的值应该是 22.59。这是怎么回事?

编辑:我在分配到ExtraSales 之后添加了额外的行,但值没有改变。

【问题讨论】:

    标签: c# linq linq-to-sql


    【解决方案1】:

    说这是一个延迟执行问题的答案是错误的。这是一个运算符优先级问题。

    摆脱那里所有完全不相关且无法阅读的代码。这都是红鲱鱼。相关的再现是:

    decimal? d1 = 11.31m;
    decimal? d2 = 11.28m;
    decimal test1 = d1 ?? 0m;
    decimal test2 = d2 ?? 0m;
    decimal test3 = test1 + test2;
    decimal test4 = d1 ?? 0m + d2 ?? 0m;
    

    最后一行是什么意思?和前面的意思一样吗?

    不,它没有。加法运算符优先级高于空值合并运算符,所以这是

    decimal test4 = d1 ?? (0m + d2) ?? 0m;
    

    您编写的代码的意思是“如果 d1 不为空,则生成 d1 的值。如果 d1 为空且 0m + d2 不为空,则生成 0m + d2 的值。如果 0m + d2 为空,则生成该值0米。”

    (您可能不知道 ?? 运算符具有这种令人愉快的链接属性。一般来说,a ?? b ?? c ?? d ?? e 会为您提供 a、b、c 或 d 的第一个非空值,如果它们全部为 e,则为null。链子想怎么编就怎么编。是个很优雅的小算子。)

    由于 d1 不为空,我们生成它的值并将 test4 分配给 d1 的值。

    你可能是想说:

    decimal test4 = (d1 ?? 0m) + (d2 ?? 0m);
    

    如果您的意思是“d1 或 d2 可以为空,如果其中一个为空,则将空一视为零”。所以 12 + 2 是 14, 12 + null 是 12, null + null 是 0

    如果你的意思是“d1 和 d2 都可以为空,如果 either 为空,那么我想要零”,那就是

      decimal test4 = (d1 + d2) ?? 0m;
    

    所以 12 + 2 是 14,12 + null 是 0,null + null 是 0

    我注意到,如果您对代码进行了格式化,以便相关文本出现在屏幕上,那么您可能不会首先收到五个左右的错误答案。尝试格式化您的代码,使其全部显示在屏幕上;如果你这样做,你会得到更好的答案。

    【讨论】:

    • 你知道我应该知道的更好。我过去在一个场景中遇到过这个优先级问题??比其他运算符具有更高的优先级。调试器似乎给了我误导性的信息。
    【解决方案2】:

    我认为您是 LINQ 中延迟执行的“受害者”。看看这篇解释这个概念的博文:

    http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx

    【讨论】:

      【解决方案3】:

      是的,它被称为延迟执行,它是非常强大的功能之一,但如果你没有预料到它也会让你绊倒......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-25
        • 2011-04-20
        • 1970-01-01
        • 2016-08-06
        • 1970-01-01
        • 1970-01-01
        • 2022-07-08
        • 2012-02-19
        相关资源
        最近更新 更多