【问题标题】:DefaultIfEmpty returning nullDefaultIfEmpty 返回 null
【发布时间】:2015-02-03 11:44:03
【问题描述】:

我正在与C#.NET4.5EF6(应该不重要)合作。

我从 db 中选择一些值,然后 .ToList() 它们,然后添加 DefaultIfEmpty(new ActualFee{Net = 0, Vat = 0}) 如果不存在,我得到 null

public static ConveyancingSummaryVm ToConveyancingSummaryVm(this Tuple<IEnumerable<ActualFee>, ConveyancingAnswer, Customer> conveyancePricingAnswersAndCustomer)
        {
            var purchaseFees = conveyancePricingAnswersAndCustomer.Item1.Where(o => o.ConveyancingSaleType == "Purchase").ToList();

            if (purchaseFees.Any())
            {
                var discount = purchaseFees.DefaultIfEmpty(new ActualFee{Net = 0, Vat = 0}).SingleOrDefault(o => o.Title.Contains("Discount")); 

                conveyancingSummaryVm.IsPurchaseFreehold = conveyancePricingAnswersAndCustomer.Item2.PropertyBoughtIsFreehold;
...

我必须在这里遗漏一些明显的东西。

【问题讨论】:

  • 很可能 SingleOrDefault 返回 null。
  • 见上面的评论——还有,为什么使用 DefaultIfEmpty 和 Any()——如果你有 'Some',它可能不能为空。
  • @Selman22 所以你是说DefaultIfEmpty 不适用于SingleOrDefault
  • 您的问题实际上很有意义,因为该方法建议“如果为空,则返回此默认值”...我不明白为什么 SingleOrDEFAULT 没有检索您建议的默认值。如果您的列表为 EMPTY(非空),您的场景可能会起作用,例如 Count=0... 在这种情况下,我认为它会返回您的默认值。

标签: c# .net linq entity-framework


【解决方案1】:

在这种情况下,DefaultIfEmpty 无法返回 null。当没有元素时,它返回一个ActualFee 实例并且Title 不包含Discount。这就是SingleOrDefault 返回null 的原因。

所以你是说 DefaultIfEmpty 不适用于 SingleOrDefault?

不,DefaultIfEmpty 有效并返回预期值。然后SingleOrDefaultDefaultIfEmpty 的返回值上运行并返回null,因为序列中没有满足您条件的元素。

您可以使用空合并运算符来获得您想要的行为:

var discount = purchaseFees.FirstOrDefault(o => o.Title.Contains("Discount")) 
              ?? new ActualFee{Net = 0, Vat = 0};

【讨论】:

  • 所以基本上是这样做的? var discount = purchaseFees.Any(o =&gt; o.Title.Contains("Discount"))? purchaseFees.Single(o =&gt; o.Title.Contains("Discount")) : new ActualFee{Net = 0, Vat = 0};
  • @Liufa 我更喜欢 FirstOrDefault 并且不需要 Any。我已经更新了我的答案
【解决方案2】:

SingleOrDefault 必须返回 null。如果DefaultIfEmpty 已返回null,它将返回Object reference not set to an instance of an object。请在没有链接的情况下重写该语句。

【讨论】:

    【解决方案3】:

    此处的操作:想出了另一种解决方法。

    而不是使用Single(),如果您愿意“牺牲”检查以使其成为单个记录,您可以使用Where()Sum() 组合。

    我知道总会有一个或零个遣散费。

    例子:

    var feeValue = legalFees.Where(o => o.Title.Contains("Severance"));
    premiumDetails.LegalFeeNet = feeValue.Sum(o => o.Net);
    premiumDetails.LegalFeeVat = feeValue.Sum(o => o.Vat);
    

    如果没有记录,则为 NetVat 返回 0,如果有 - 返回值。

    更新 - 想出另一个:

    legalFees.Where(o =&gt; o.Title.Contains("Severance")).Union(new ActualFee{Net = 0, Vat = 0}).First();

    如果Where() 确实返回了一些东西,那么First() 将是Contains("Severance") 的值,如果它没有返回 - 那么First() 将是Union() 中的任何值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-07
      • 2021-04-13
      • 1970-01-01
      • 2020-06-28
      • 1970-01-01
      • 1970-01-01
      • 2020-04-22
      • 1970-01-01
      相关资源
      最近更新 更多