Reputation: 61519
I am working with C#
, .NET4.5
, EF6
(shouldn't matter really).
I am selecting some values from db then .ToList()
them and then adding DefaultIfEmpty(new ActualFee{Net = 0, Vat = 0})
if one does not exist, and I get 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;
...
I must be missing something obvious here.
Upvotes: 3
Views: 7217
Reputation: 101731
There is no way for DefaultIfEmpty
to return null in this case. When there is no element it returns an ActualFee
instance and the Title
does not contain Discount
. So that's why SingleOrDefault
returns null
.
so you are saying that DefaultIfEmpty does not work for SingleOrDefault?
No, DefaultIfEmpty
works and returns the expected value. And then SingleOrDefault
runs on the return value of DefaultIfEmpty
and returns null because there is no element in the sequence that satisfies your condition.
You can use null coalescing operator to get the behaviour you want:
var discount = purchaseFees.FirstOrDefault(o => o.Title.Contains("Discount"))
?? new ActualFee{Net = 0, Vat = 0};
Upvotes: 5
Reputation: 61519
OP here: Figured another workaround.
Rather than using Single()
if you are willing to 'sacrifice' the check for it to be single record what you can do is use Where()
and Sum()
combo.
I know there's always one or zero Severances.
Example:
var feeValue = legalFees.Where(o => o.Title.Contains("Severance"));
premiumDetails.LegalFeeNet = feeValue.Sum(o => o.Net);
premiumDetails.LegalFeeVat = feeValue.Sum(o => o.Vat);
if there are no records this returns 0
for Net
and Vat
and if there is - returns the values.
UPDATE - Figured another one:
legalFees.Where(o => o.Title.Contains("Severance")).Union(new ActualFee{Net = 0, Vat = 0}).First();
if Where()
does return something then First()
will be the value that Contains("Severance")
, if it does not - then First()
will be whatever is in Union()
.
Upvotes: 0
Reputation: 918
SingleOrDefault
must've returned null
. If DefaultIfEmpty
had returned null
, it would've returned a Object reference not set to an instance of an object
. Please rewrite that statement without chaining.
Upvotes: 2