-
Type: Bug
-
Resolution: Unresolved
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Serialization
-
None
When the T of a collection is an interface, the type discriminators do not get added properly to a query. One of two things happens depending on how you query them
- The type discriminator isn't added at all
- The type discriminator added is incorrect.
The _t for each document in the database is correctly serialized, this appears to only be an issue for reading.
Reproduction script:
Reproduction
async Task Main() { var client = new MongoClient(); var db = client.GetDatabase("polymorphismTest"); var col = db.GetCollection<IFoo>("iFoo"); // Clean up any existing documents await col.DeleteManyAsync(Builders<IFoo>.Filter.Empty); // Insert 2 new test documents of different types, each implementing IFoo await col.InsertOneAsync(new Widget1() { Id = ObjectId.GenerateNewId(), SomeField = "ABC", Bar = 10 }); await col.InsertOneAsync(new Widget2() { Id = ObjectId.GenerateNewId(), SomeField = "ABC", Bar = 10M }); // Build a query using .OfType<> on the collection. var widget1QueryColOfType = col.OfType<Widget1>().Find(Builders<Widget1>.Filter.Eq(x => x.SomeField, "ABC")); var widget2QueryColOfType = col.OfType<Widget2>().Find(Builders<Widget2>.Filter.Eq(x => x.SomeField, "ABC")); Console.WriteLine("OfType<> on the Collection"); Console.WriteLine(widget1QueryColOfType.ToString()); Console.WriteLine(widget2QueryColOfType.ToString()); Console.WriteLine(); // Build a query using .OfType<> on the Builder to change from IFoo to the concrete type. var widget1QueryBuilderOfType = col.Find(Builders<IFoo>.Filter.OfType<Widget1>(Builders<Widget1>.Filter.Eq(x => x.SomeField, "ABC"))); var widget2QueryBuilderOfType = col.Find(Builders<IFoo>.Filter.OfType<Widget2>(Builders<Widget2>.Filter.Eq(x => x.SomeField, "ABC"))); Console.WriteLine("OfType<> on the Builder"); Console.WriteLine(widget1QueryBuilderOfType.ToString()); Console.WriteLine(widget2QueryBuilderOfType.ToString()); Console.WriteLine(); Console.WriteLine("Documents in the database"); var rawDocsInDatabase = await db.GetCollection<BsonDocument>("iFoo").Find(Builders<BsonDocument>.Filter.Empty).ToListAsync(); foreach(var doc in rawDocsInDatabase) Console.WriteLine(doc.ToJson()); } public interface IFoo { ObjectId Id { get; set;} string SomeField { get; set;} } public class Widget1 : IFoo { public ObjectId Id {get;set;} public string SomeField { get; set; } public int Bar { get; set; } } public class Widget2 : IFoo { public ObjectId Id {get;set;} public string SomeField { get; set; } public Decimal Bar { get; set; } }
Output
OfType<> on the Collection find({ "SomeField" : "ABC" }) find({ "SomeField" : "ABC" }) OfType<> on the Builder find({ "_t" : "UserQuery+Widget1, LINQPadQuery", "SomeField" : "ABC" }) find({ "_t" : "UserQuery+Widget2, LINQPadQuery", "SomeField" : "ABC" }) Documents in the database { "_id" : ObjectId("589347de303cd5d0ca4540e4"), "_t" : "Widget1", "SomeField" : "ABC", "Bar" : 10 } { "_id" : ObjectId("589347de303cd5d0ca4540e6"), "_t" : "Widget2", "SomeField" : "ABC", "Bar" : "10" }
- depends on
-
CSHARP-5356 Support `OfType` and `is` with scalar discriminators when using class mapped serializers
- In Code Review