Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-1907

Type discriminators don't work when collection document type is an interface

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major - P3
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Serialization
    • Labels:
      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

      1. The type discriminator isn't added at all
      2. 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" }
      

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            peter.garafano Peter Garafano
            Votes:
            2 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated: