-
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
-
- Closed
-
- is depended on by
-
CSHARP-4935 Support casting from an interface to a type that implements that interface in LINQ queries
-
- Closed
-