An Expression Tree Lambda May Not Contain a Null Propagating Operator

An expression tree lambda may not contain a null propagating operator

The example you were quoting from uses LINQ to Objects, where the implicit lambda expressions in the query are converted into delegates... whereas you're using EF or similar, with IQueryable<T> queryies, where the lambda expressions are converted into expression trees. Expression trees don't support the null conditional operator (or tuples).

Just do it the old way:

price = co == null ? 0 : (co.price ?? 0)

(I believe the null-coalescing operator is fine in an expression tree.)

Error: An expression tree lambda may not contain a null propagating operator for Linq with from

This is a weird rule of LINQ. The problem is in the expression:

InspectedCompanyName = (from a in contacts where a.ContactId == r.InspectedCompanyDataId select a.FirstName)?.FirstOrDefault()

which is inside your select. ?. is not allowed.

Thankfully, ?: (the ternary operator/inline conditional) is allowed, so this can be rewritten. For convenience you need a let:

myOrphanList =
(
from v in allViolations
from r in allInspectionResults
from i in allItems
where
r.InspectionResultId == i.InspectionResultId &&
i.InspectionItemId == v.InspectionItemId
let firstName = from a in contacts // Pop your sub-query in a variable here
where a.ContactId == r.InspectedCompanyDataId
select a.FirstName
select new OrphanViolationsReport
{
ViolationId = v.ViolationId,
ViolationNumber = v.ViolationNumber,
ViolationDate = v.ViolationDate,
ViolationType = v.ViolationType.ViolationTypeCode,
ItemYear = i.ItemYear,
ItemMakeManufacturer = i.ItemMakeManufacturer,
ItemModel = i.ItemModel,
VIN = i.VIN,
PIN = i.PIN,
InspectionResultId = r.InspectionResultId,
InspectionResultNumber = r.InspectionRequestNumber,
DealerDmvNumber = r.DealerDmvNumber,
// USe ternary operator here
InspectedCompanyName = firstName == null ? null : firstName
}
).ToList();

This is too complex for me to test compile, but that's basically the idea.

That said, as @SalahAkbari points out, the logic here is very strange. A select query (the one I've put into firstName) will never return null, it will return an empty collection, so what's the point?

Automapper 8 - An expression tree lambda may not contain a null propagating operator

New Func-based overloads in Automapper 8.0.0 accept more parameters compared to old/removed ResolveUsing overloads.

Instead of using lambda expression with single input parameter opt.MapFrom(src => ...) when replacing ResolveUsing, overload with 2 parameters should be used opt.MapFrom((src, dest) => ...).

MapFrom expression becomes:

opt => opt.MapFrom((src, dest) => src?.Customer ?? new Customer())

Full example:

CreateMap<SourceType, DestinationType>()
.ForMember(dest => dest.Customer,
opt => opt.MapFrom((src, dest) => src?.Customer ?? new Customer())
);

Why can't I use the null propagation operator in lambda expressions?

It's complicated since expression tree lambdas (unlike delegate lambdas) are interpreted by already existing LINQ providers which don't yet support null propagating.

Converting to a conditional expression is not always accurate as there are multiple evaluations while with ?. there's only a single evaluation for example:

customer.Where(a => c.Increment()?.Name) // Written by the user 
customer.Where(a => c.Increment() == null ? null : c.Increment().Name) // Incorrectly interpreted by an old LINQ provider

You can go deeper in the relevant discussion on CodePlex where 3 solutions are offered: NullPropagationExpression, ConditionalExpression & a hybrid

Expression Tree for o?.Value

Normally, if you want to know how to construct an expression tree for some expression, you let the C# compiler do it and inspect the result.

But in this case, it won't work, because "An expression tree lambda may not contain a null propagating operator." But you don't actually need the null propagating operator, you just need something that behaves like one.

You can do that by creating an expression that looks like this: o == null ? null : o.Value. In code:

public Expression CreateNullPropagationExpression(Expression o, string property)
{
Expression propertyAccess = Expression.Property(o, property);

var propertyType = propertyAccess.Type;

if (propertyType.IsValueType && Nullable.GetUnderlyingType(propertyType) == null)
propertyAccess = Expression.Convert(
propertyAccess, typeof(Nullable<>).MakeGenericType(propertyType));

var nullResult = Expression.Default(propertyAccess.Type);

var condition = Expression.Equal(o, Expression.Constant(null, o.Type));

return Expression.Condition(condition, nullResult, propertyAccess);
}

Test Null after FirstOrDefault

Select the Name of the ProductType that you want before your FirstOrDefault:

Name = product.ProductType.ProductTypesI18N
.Where(productType => productType.LanguageCode == languageCode)
.Select(productType => productType.Name)
.FirstOrDefault(),

Simple comme bonjour!

What is a correct way to select a property of optional navigation property in Entity Framework?

Why not use a conditional operator?

CaseRelationTypeName = (rc.CasesRelationType != null) ? rc.CasesRealtionType.Name : null;


Related Topics



Leave a reply



Submit