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

Adding array member to collection model causes error during subsequent deserialisation

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 2.0.1
    • Component/s: Serialization
    • None

      Types:

      
              class ContainerV1
              {
                  public string Id { get; set; }
                  public bool A { get; set; }
              }
      
              class ContainerV2
              {
                  public string Id { get; set; }
                  public bool A { get; set; }
                  public SubItem[] Blah { get; set; }
              }
      

      Code:

                  var mongo = new MongoClient("mongodb://localhost");
      
                  // start from scratch
                  mongo.DropDatabaseAsync("foo").GetAwaiter().GetResult();
                  var test = mongo.GetDatabase("foo");
      
                  // insert ContainerV1 record (without array member)
                  var coll1 = test.GetCollection<ContainerV1>("bar");
                  var item = new ContainerV1 { Id = Guid.NewGuid().ToString("N"), A = true };
                  coll1.InsertOneAsync(item).GetAwaiter().GetResult();
      
                  // get from same collection after model changes.
                  var coll2 = test.GetCollection<ContainerV2>("bar");
                  var results = coll2.AsQueryable().Where(i => i.A).Select(i => new { Blah = i.Blah }).ToArray();
      

      The exception: "No matching creator found." (BsonSerializationException), from BsonClassMapSerializer.ChooseBestCreator.

      The reason:

      Here's the server command:

      { "aggregate" : "bar", "pipeline" : [{ "$match" : { "A" : true } }, { "$project" : { "Blah" : "$Blah", "_id" : 0 } }], "cursor" : { } }

      The response:

      { "cursor" : { "id" : NumberLong(0), "ns" : "foo.bar", "firstBatch" : [{ }] }, "ok" : 1.0 }

      Basically, the array part of the projection comes back as an empty document when it doesn't exist, as would be the case when the member is new. BsonClassMapSerializer.DeserializeClass() doesn't populate any values from it of course, and no missing values are populated because the array member is marked IsReadOnly.

      In ChooseBestCreator, the MostArgumentsCreatorSelector() looks for an appropriate creator, but with no values it can't determine one.

      I'm not 100% on what the bug is, but perhaps - looking at DeserializeClass() - MemberMap.IsReadOnly for the array property of the projection should not be null, or should not be checked for null when dealing with missing values?

      (Marking as minor since I'm not sure if the deserialisation code should be expected to deal with whatever crazy cases might be thrown at it like this)

            Assignee:
            wan.bachtiar@mongodb.com Wan Bachtiar
            Reporter:
            kierenj Kieren Johnstone
            Votes:
            6 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated:
              Resolved: