Client-side casting with LINQ3 projection throws Expression not supported exception

The following code that does a client-side filter and cast of the sub-document elements in an array field in the projection always worked with drivers prior to 2.19 using the LINQ2 provider. Running in 2.19 with the default LINQ3 provider will throw an “Expression not supported: a.ArrayOfX.OfType()” exception. When setting the provider to LINQ2, this works as expected.

var projection = Builders<ClassA>.Projection.Expression(a => new ClassB {
	ClassId = a.ClassId,
	ArrayValues = a.ArrayOfX.OfType<SubclassOfX>().ToList()

var query = database.GetCollection<ClassA>("ClassA")
	.Find(a => a.ClassId == myId)
var a = query.ToString();

Same exception occurs when using aggregation pipeline with AsQueryable().Where().Select().

Changing the cast to something like a.ArrayOfX.Where(x => x is SubclassOfX).Cast<SubclassOfX>().ToList() also works with LINQ2 but not LINQ3.

Does LINQ3 no longer support expressions with client-side custom code/functions/lambdas? This is a very powerful capability as you can do things in a single operation with very clean code instead of having to do the two steps of materializing the results from the mongodb query into an anonymous class and then doing another client side LINQ copy + transformation over that to get it into its final form.

Hi, Jasper,

Welcome to the MongoDB Community Forums!

I understand that you’re having a problem with a projection that works with LINQ2 but fails with LINQ3.

LINQ2 would attempt to translate as much of the expression to MQL as it could and then run the remainder on the client side. This led to code that was difficult to reason about since you wouldn’t know by looking at the code which portions executed server side and which client side.

In LINQ3 we decided to make this explicit by throwing ExpressionNotSupportedException for any expression that we could not translate into MQL. The intention is to require the separation of server-side and client-side projections. More details can be found in CSHARP-4498.

In theory we could potentially support IEnumerable.OfType<TResult> in MQL using $expr and type discriminators on the array’s subdocuments. If such a feature would be valuable to you, please file a feature request.

Please let us know if you have any additional questions.