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

Exception when querying via interface class

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 2.9.2
    • Component/s: Serialization
    • Labels:
      None
    • Environment:
      Windows

      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:
            Unassigned Unassigned
            Reporter:
            jevon.kendon@mbie.govt.nz Jevon Kendon
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: