Exception when querying via interface class

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Gone away
    • Priority: Major - P3
    • None
    • Affects Version/s: 2.9.2
    • Component/s: Serialization
    • None
    • Environment:
      Windows
    • None
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?
    • None
    • None
    • None
    • None
    • None
    • None

      Even though this issue is closely related to CSHARP-485, consider this small unit-test.

      using System;
      using System.Threading.Tasks;
      using Mongo2Go;
      using MongoDB.Bson.Serialization;
      using MongoDB.Bson.Serialization.Conventions;
      using MongoDB.Driver;
      using Xunit;namespace IntegrationTest
      {
          public class MongoTestHelper : IDisposable
          {
              private readonly MongoDbRunner _runner;
              private readonly IMongoDatabase _db;                                        public MongoTestHelper(string databaseName, bool debug = false)
              {
                  if (debug)
                  {
                      _runner = MongoDbRunner.StartForDebugging();
                  }
                  else
                  {
                      _runner = MongoDbRunner.Start();
                  }                                   var mongo = new MongoClient(_runner.ConnectionString);
                  _db = mongo.GetDatabase(databaseName);
              }                public IMongoDatabase GetDatabase()
              {
                  return _db;
              }                public void Dispose()
              {
                  _runner.Dispose();
              }
          }        public class AnimalTests : IDisposable
          {
              private readonly MongoTestHelper _helper;                        public AnimalTests()
              {
                  var conventionPack = new ConventionPack
                  {
                      new IgnoreExtraElementsConvention(true)
                  };
                  ConventionRegistry.Register("IgnoreExtraElements", conventionPack, type => true);                     BsonClassMap.RegisterClassMap<Dog>();
                  BsonClassMap.RegisterClassMap<Cat>();
                  // var dogSerializer = BsonSerializer.LookupSerializer<Dog>();
                  // BsonSerializer.RegisterSerializer<IAnimal>(new ImpliedImplementationInterfaceSerializer<IAnimal, Dog>(dogSerializer));
                  //
                  // var catSerializer = BsonSerializer.LookupSerializer<Cat>();
                  // BsonSerializer.RegisterSerializer<IAnimal>(new ImpliedImplementationInterfaceSerializer<IAnimal, Cat>(catSerializer));
                  //
                  // because:
                  //   MongoDB.Bson.BsonSerializationException : There is already a serializer registered for type IAnimal.
                  _helper = new MongoTestHelper("db_test", true);
              }               [Fact]
              public async Task Some_Test()
              {
                  var animals = new IAnimal[]
                  {
                      new Dog(), 
                      new Cat()
                  };                        var db = _helper.GetDatabase();
                  db.DropCollection("animal");
                  var collWrite = db.GetCollection<IAnimal>("animal");
                  
                  collWrite.InsertMany(animals);                        var collRead = db.GetCollection<IAnimal>("animal");            // THIS WORKS
                  await (await collRead.FindAsync(x => true)).ToListAsync();            // THIS DOESN'T
                  await (await collRead.FindAsync(x => x.Type == "dog")).ToListAsync();
              }                public void Dispose()
              {
                  _helper.Dispose();
              }                    public interface IAnimal
              {
                  string Type { get; set; }
                  string Speak { get; set; }
              }                public class Dog : IAnimal
              {
                  public string Type { get; set; }
                  public string Speak { get; set; }            public Dog()
                  {
                      Type = "dog";
                      Speak = "woof";
                  }
              }                public class Cat : IAnimal
              {
                  public string Type { get; set; }
                  public string Speak { get; set; }            public Cat()
                  {
                      Type = "cat";
                      Speak = "meow";
                  }
              }
          }
      } 

      It fails with error:

      Message: 
          System.InvalidOperationException : {document}.Type is not supported.
        Stack Trace: 
          PredicateTranslator.GetFieldExpression(Expression expression)
          PredicateTranslator.TranslateComparison(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
          PredicateTranslator.Translate(Expression node)
          PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry)
          MongoCollectionImpl`1.CreateFindOperation[TProjection](FilterDefinition`1 filter, FindOptions`2 options)
          MongoCollectionImpl`1.FindAsync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
          <>c__DisplayClass43_0`1.<FindAsync>b__0(IClientSessionHandle session)
          MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)
          AnimalTests.Some_Test() line 92
          --- End of stack trace from previous location where exception was thrown --- 

      The difference is two concrete classes that use interface IAnimal. For that reason, I can't use the explicit serializer registration.

      Though this example is contrived, it reflects a real world problem I was hoping to solve.

      In the meantime, I've had to resort to a plan BSON search:

      var filter = new BsonDocument {{"Type", "dog"}}; 

       

            Assignee:
            Boris Dogadov
            Reporter:
            Jevon Kendon
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: