[CSHARP-4763] Consider supporting client side projections with Find in LINQ3 Created: 18/Aug/23  Updated: 06/Feb/24

Status: Scheduled
Project: C# Driver
Component/s: LINQ3
Affects Version/s: 2.21.0
Fix Version/s: None

Type: Improvement Priority: Unknown
Reporter: Robert Stam Assignee: Robert Stam
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
is duplicated by CSHARP-4588 LINQ3 LinqProvider do not support pub... Closed
is duplicated by CSHARP-4548 IFindFluent.Projection fails with Exp... Closed
is duplicated by CSHARP-4498 .Project(c => c.Reference()) not work Closed
is duplicated by CSHARP-4705 ExpressionNotSupportedException with ... Closed
is duplicated by CSHARP-4956 ExpressionNotSupported Exception afte... Closed
Related
related to CSHARP-4759 Improve error message for client side... Backlog

 Description   

The following works in LINQ2 but not in LINQ3:

 var find = collection
     .Find(x => x.Id == 1)
     .Project(x => new { R = MyFunction(x.X) }); // MyFunction cannot be translated to MQL

The following doesn't work with either LINQ provider:

var queryable = collection.AsQueryable()
    .Where(x => x.Id == 1)
    .Select(x => new { R = MyFunction(x.X) }); // MyFunction cannot be translated to MQL

When writing the new LINQ3 provider we made the deliberate decision to not support implicit client side projections for the following reasons:

  • they only work on the final Select
  • adding any additional stages after a final Select with implicit client side projections breaks the query
  • they can hide inefficiency because more data than expected might be fetched to the client

We felt that client side projections should be explicit so that users writing and reading code know exactly what is happening server side and what is happening client side.

The above two examples can be refactored to use explicit client side projections as follows:

var find = collection
    .Find(x => x.Id == 1)
    .ToEnumerable() // execute the rest of this chain client side
    .Select(x => new { R = MyFunction(x.X) });

and

var enumerable = collection.AsQueryable()
    .Where(x => x.Id == 1)
    .AsEnumerable() // execute the rest of this chain client side
    .Select(x => new { R = MyFunction(x.X) });

While our decision to not support implicit client side projections is reasonable, nonetheless it is a breaking change from LINQ2 (at least with respect to `Find`). In addition, in spite of the potential inefficiencies that implicit client side projections might hide some users want the convenience of it anyway.


Generated at Wed Feb 07 21:49:17 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.