How to support entity type converting in LinqProvider.V3

Trying convert entity type in the conditional expression, unfortunately it doesn’t work. Is there other solution can help this.

My information

Hi, @chock_chen,

Welcome to the MongoDB Community Forums. I understand that you’re trying to perform a cast in a where predicate using LINQ3, but it is failing. Cast operations map to the $convert function on the server and it is only able to convert to certain well known types such as numbers, strings, dates, and ObjectIds. Notably it doesn’t understand any user-defined types specified in C# class definitions or JSON schema definitions.

If you’re trying to query for properties on a derived type, you can use OfType<T>(), which eliminates the need for a cast:

var coll = database.GetCollection<Asset>("Asset");
var query = coll.AsQueryable()
                .OfType<Equipment>()
                .Where(x => x.Supplier == "Supplier");

Console.WriteLine(query);

Output:

test.asset.Aggregate([{ "$match" : { "_t" : "Equipment" } }, { "$match" : { "Supplier" : "Supplier" } }])

Note the query on the type discriminator _t. The exact predicate will depend on how you’ve configured your type hierarchy mapping. See Polymorphism in the documentation for more information.

Sincerely,
James

Hi, @James_Kovacs ,
Thank you for your feedback! If the retrieval field comes from one derived class, it works just fine by your way. But from my case there are two derived classes (Equipment and Busbar) in the Linq expression, There seems no way to get results from a single query. :grinning:

Hi, @chock_chen,

Given how you’ve defined your class hierarchy, there is no way to express the query in C#. You can however express it in MQL using AppendStage<TResult> and the matcher expressed using BSON.

var client = new MongoClient();
var db = client.GetDatabase("test");
var coll = db.GetCollection<Asset>("coll");

var matcher = new BsonDocument {
    { nameof(Equipment.Supplier), "Supplier" },
    { nameof(Busbar), "Number" }
};

var query = coll.Aggregate().Match(matcher);

foreach (var result in query.ToList())
{
    Console.WriteLine(result);
}

Depending on how you persist your Asset class hierarchy, you will need to add [BsonIgnoreExtraElements] to certain classes or project out only the valid fields for a particular class. For example, if the returned BSON contains both Supplier and Number fields, then it cannot be deserialized into either an Equipment or Busbar object because there is an extra field.

I would strongly encourage you to reconsider class models and database schema so that they are logically consistent. If you need to query on both Supplier and Number, you should have a C# base class that contains both those properties rather than relying on hand-rolled MQL.

Sincerely,
James

Hi, @James_Kovacs ,
I’m going to consider your suggestion to update class models. Thanks a lot for your help!!!