Details
-
Bug
-
Resolution: Unresolved
-
Major - P3
-
None
-
None
-
None
Description
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" }
|