[CSHARP-4367] Support custom LINQ translators Created: 15/Oct/22  Updated: 28/Nov/22

Status: Backlog
Project: C# Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

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


 Description   

The current implementation of mongo driver's LINQ provider throws an `ExpressionNotSupportedException` when it fails to find a built-in translator for a LINQ expression it encounters.

Has there been any consideration to allowing users of the library to provide their own custom translators in order to open up support to other use cases that are not implemented by the library?

I'm currently working on a library which implements BSON serialization of geometry types defined by `NetTopologySuite`
`NetTopologySuite` has been chosen by EF Core as the standard for defining geometry types and it provides packages which add serialization and LINQ support for it.

For example the following model and query are automatically serialized and translated into a database query.

using NetTopologySuite.Geometries;
 
public class Model
{
        public Point Location { get; init; } = default!;
}
 
...
 
queryable.Where(m => m.Location.Within(new Polygon(new LinearRing(new Coordinate[] { new(0, 1), new(0, -1), new(1, -1), new(1, 1), new(0, 1), }))));

 In projects following Onion Architecture, using `NetTopologySuite` allows for decoupling Domain models from the persistence layer, allowing for the database technology to be swapped out without changes to the Domain layer.

On top of that HotChocolate which implements GraphQL for .NET have built-in support for translating GraphQL queries like the following one into a LINQ expression which uses `NetTopologySuite`

query Models {
    models(where: {
        location: {
            within: {
                geometry: {
                    type: Polygon,
                    coordinates: [
                        [
                            [20 20],
                            [140 20],
                            [120 100],
                            [20 100 ],
                            [20 20]
                        ]
                    ]
                }
            }
        }
    }){
        location {
            coordinates
        }
    }
} 

translates to:

queryable.Where(m => m.Location.Within(new Polygon(new LinearRing(new Coordinate[] { new(20, 20), new(140, 20), new(120, 100), new(20, 100), new(20, 20) }))));

Put together, it can be very powerful and removes a lot of the boilerplate code required in order to make geospatial queries directly from the frontend all the way to Mongo or SQL server, all while maintaing separation and decoupling between different layers of the application.

Currently, we're in the process of migrating from SQL Server to MongoDB and having the option to leave our Domain logic mostly untouched and for our frontend's GraphQL queries to continue working with minimal changes is very appealing.

With the help of MongoDB.NetTopologySuite.Serialization library that I'm writing and the ability to extend current LINQ provider implementation, that can make our migration a lot easier.

Is this something that has been given consideration, and would you be open to accepting a PR if I have a crack and introducing extensibility points in the code?



 Comments   
Comment by Wassim Khalil [ 28/Nov/22 ]

Just an update, MongoDB.NetTopologySuite.Serialization nuget package is now available and adds full support for serializing/deserialzing NetTopologySuite models to/from BSON.

Looking forward to hearing an update about LINQ3 user-extensibility in the future.

Comment by Robert Stam [ 25/Oct/22 ]

We have at times in the past considered making the LINQ3 translators extensible by the user, and while we like the idea in principle we are just not ready to do it yet.

To do so we would have to make public a plug-in architecture and make public much of the underlying LINQ machinery related classes for a user-written plug-in to consume.

We will consider a user-extensible LINQ3 plug-in architecture in a future release.

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