1

I use the mongoDB C# driver 2.1.1 to store and retrieve documents in a mongoDb collection. This worked well so far until one document was CORRECTLY stored but could not be read back by the driver.

I got to that conclusion using robomongo (a user interface to monitor what's inside my collection) and manipulating the object stored. It contains a collection of elements (around 4000 sub elements) and if I remove enough of it, the document is finally retrievable again.

The line of code used is:

    public Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default(CancellationToken))
    {
        return MongoQueryable.FirstOrDefaultAsync(_collection, predicate, cancellationToken);
    }

Before you ask, what I first thought is that one specific element of my sub elements set had encountered some issues while being serialized/deserialized and was creating the issue. I tested by removing randomly elements of the collection, and just the number seems to be the root of the problem.

The text file size of the Json document represents around 11 Mb - I will try now to get the actual size of the object which would be more relevant.

Something else I can add is that in the mondoDb log file, there is one line that only appear when I try to select an "oversized" document :

2016-06-29T19:30:45.982+0200 I COMMAND  [conn12] command MYCOLLECTIONDb.$cmd command: aggregate 
{ aggregate: "XXXX", pipeline: [ { $match: { _id: "5773e0e9a1152d259c7d2e50" } }, { $limit: 1 } ]
, cursor: {} } keyUpdates:0 writeConflicts:0 numYields:0 reslen:4188200 locks:{ Global:
 { acquireCount: { r: 6 } }, MMAPV1Journal: { acquireCount: 
{ r: 3 } }, Database: { acquireCount: { r: 3 } }, Collection: { acquireCount: { R: 3 } } } 109ms

(XXXX being my custom object)

So I'd like to know if you have any idea of what's causing this issue, any hint of where I should try to look, because I am running out of ideas :)

EDIT_1: That is basically the structure of my object :

[DataContract]
public class MyClass
{
    [DataMember]
    public string _id { get; set; }

    [DataMember]
    public string XmlPreference { get; set; }

    [DataMember]
    public string XmlMarketDates { get; set; }

    [DataMember]
    public IEnumerable<ClassB> Lines { get; set; }
}

[DataContract]
public class ClassB
{
    [DataMember]
    public string UniqueId { get; set; }

    [DataMember]
    public string ParentId { get; set; }

    [DataMember]
    public Dictionary<string, ClassC> DataMapping {get; set;}
}

and ClassC is just a container of 7 ints and 1 object properties. Still looking for something :)

EDIT 2: I reproduced the bug only using the mongoDb C# drivers 2.1.1 release version. Here is the code :

using MongoDB.Bson;
using MongoDB.Driver.Linq;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace TestingMongoDbCsharpDriver
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Debugging starting...");

            try 
            {
                MongoDB.Driver.MongoClient myClient = new MongoDB.Driver.MongoClient("mongodb://localhost:27010");
                var db = myClient.GetDatabase("DocumentStoreDb");
                var collection = db.GetCollection<DocumentModel>("TestOverload");

                Console.WriteLine("Collection TestOverload found");


                Random rand = new Random(999999999);
                DocumentModel toInsert = null;
                for (int lineNb = 1; lineNb < 50000; lineNb += 1000)
                {
                    string id = rand.Next().ToString();
                    Console.WriteLine(string.Format("\nCreating document with id '{0}' and {1} lines...", id, lineNb));
                    toInsert = Funcs.Create(id, lineNb);
                    Console.WriteLine("Created.");

                    // Saving and waiting for it to finish
                    collection.InsertOneAsync(toInsert).Wait();
                    Console.WriteLine("Inserted.");

                    // retrieving it
                    var filter = new BsonDocument("_id", new BsonDocument("$eq", id));

                    var cursor = collection.FindAsync<DocumentModel>(filter).Result;                    
                    cursor.MoveNextAsync().Wait();
                    string messFilterMethod = cursor.Current.Count() == 1 ? "Retrieved" : "Not retrieved. Bug confirmed";
                    Console.WriteLine("With Filter: " + messFilterMethod);

                    var model = MongoQueryable.FirstOrDefaultAsync(collection.AsQueryable(), e => e._id == id).Result;
                    string mess = model != null ? "Retrieved" : "Not retrieved. Bug confirmed";
                    Console.WriteLine("With AsQueryable: " + mess);

                    // Removing it
                    collection.DeleteOneAsync(filter).Wait();
                    Console.WriteLine("Deleted.\n");

                    Console.ReadKey();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\n\nERROR: " + e.Message);
            }
            Console.WriteLine("\n\n**************** NO BUG *************\n");
        }

    }


    public static class Funcs 
    {
        public static DocumentModel Create(string uniqueId, int nbLines)
        {
            Random random = new Random(2000000);
            List<MyDocumentSubElement> listOk = new List<MyDocumentSubElement>();

            for (int lines = 0; lines < nbLines; ++lines)
            {
                Dictionary<string, SnapCellValueStyle> newDico = new Dictionary<string, SnapCellValueStyle>();
                for (int i = 0; i < 10; ++i)
                {
                    int idSnap = random.Next();
                    var snap = new SnapCellValueStyle()
                    {
                        alignment = idSnap,
                        Value = "okkkkkkkkkkzzzzkk"
                    };
                    newDico.Add("newKey_" + idSnap.ToString(), snap);
                }

                MyDocumentSubElement doc = new MyDocumentSubElement()
                {
                    Icon = 516,
                    Name = "name du truc",
                    ParentId = "parent id",
                    type = SubElementType.T3,
                    UniqueId = "uniqueId_" + random.Next().ToString(),
                    MapColumnNameToCellValue = newDico
                };
                listOk.Add(doc);
            }

            int headerId = random.Next();
            MyDocumentHeader temp = new MyDocumentHeader()
            {
                Comment = "comment",
                Date = DateTime.Now,
                ExtractionId = headerId,
                Id = "id ok _ " + headerId,
                Name = "Name really interesting name",
                OwnerId = 95115,
                RootFolioId = 51,
                SnapshotViewId = MyDocumentType.Type2
            };

            DocumentModel toInsert = new DocumentModel()
            {
                _id = uniqueId,
                Header = temp,
                XmlMarketDates = "<xmlPrefok65464f6szf65ze4f6d2f1ergers5fvefref3e4f05e4f064z68f4xd35f8eszf40s6e40f68z4f0e8511xf340ed53f1d51zf68d4z61ef644dcdce4f64zef84zOKok>><>>",
                XmlPreference = "<<zefaiunzhduiaopklzpdpakzdplapdergergfdgergekâzda4684z16ad84s2dd0486za04d68a04z8d0s1d d4az80d46az4d651s1d8 154efze40f6 4ze65f40 65ze40f6z4e>><>>>",
                Lines = listOk
            };

            return toInsert;
        }  
    }

    // Imitation of SnapshotDocModel
    [DataContract]
    public class DocumentModel
    {
        [DataMember]
        public string _id { get; set; }

        [DataMember]
        public MyDocumentHeader Header { get; set; }

        [DataMember]
        public string XmlPreference { get; set; }

        [DataMember]
        public string XmlMarketDates { get; set; }

        [DataMember]
        public IEnumerable<MyDocumentSubElement> Lines { get; set; }
    }

    [DataContract]
    public class MyDocumentHeader
    {
        [DataMember]
        public string Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public int OwnerId { get; set; }
        [DataMember]
        public string Comment { get; set; }
        [DataMember]
        public DateTime Date { get; set; }
        [DataMember]
        public int RootFolioId { get; set; }
        [DataMember]
        public MyDocumentType SnapshotViewId { get; set; }
        [DataMember]
        public int ExtractionId { get; set; }
    }

    [DataContract]
    public class MyDocumentSubElement
    {
        [DataMember]
        public string UniqueId { get; set; }

        [DataMember]
        public string ParentId { get; set; }

        [DataMember]
        public int Icon { get; set; }

        [DataMember]
        public SubElementType type { get; set; }

        [DataMember]
        public Dictionary<string, SnapCellValueStyle> MapColumnNameToCellValue { get; set; }

        [DataMember]
        public string Name { get; set; }
    }

    public class SnapCellValueStyle
    {
        public object Value { get; set; }
        public int alignment { get; set; }
        public int Red { get; set; }
        public int Green { get; set; }
        public int Blue { get; set; }
        public int currency { get; set; }
        public int decimalPoint { get; set; }
        public int kind { get; set; }
        public int style { get; set; }
    }

    #region enum
    public enum MyDocumentType
    {
        Undefined,
        Type1,
        Type2,
        Type3,
        Type4,
        Type5
    }

    public enum SubElementType
    {
        T1,
        T2,
        T3
    }
    #endregion
}

If you test it, you will see that there is the point where the AsQueryable method does not work anymore where as the document is still retrievable by the method using a filter.

DevBackFlo
  • 94
  • 8
  • could you post a document structure (barebone)? Will try to reproduce this with 2.2.4 driver – profesor79 Jul 05 '16 at 10:35
  • Could be this bug: I don't remember the exact number required for this bug to get hit though. Please upgrade to 2.2.4 and see if there problem goes away. https://jira.mongodb.org/browse/CSHARP-1607 – Craig Wilson Jul 05 '16 at 11:05
  • @profesor79 as Craig Wilson suggested, it may be related to the driver version. I'll try with the new one and see how it goes ! If that is unsuccesful, I'll post a generic version of my class :) – DevBackFlo Jul 05 '16 at 12:35
  • no problem with my dummy class I wen up to 16767843 bytes – profesor79 Jul 05 '16 at 12:36
  • Hey. So... I still haven't try the 2.2.4 version as I need it signed. So that may take a bit more time :) I really hope it is related to @CraigWilson bug. Basically, my backbone structure is not that complicated (I'll update the quesiton, I am testing at the same time hoping to find something) – DevBackFlo Jul 05 '16 at 13:48
  • @CraigWilson: Hi again guys. I have been doing some more testing. I have reached a point where adding or removing a character from an id makes the JSon Document un retrievable by the mongoDb C# driver. I'll definitely try with the 2.2.4 version, but this bug looked more related to the number of instances in an array. Here, that definitely looks like an overflow or something no? What bugs me is that storing works fine.... – DevBackFlo Jul 05 '16 at 15:58
  • @CraigWilson : Hi Craig. I edited my problem with a sample to reproduce the bug. I just checked the JIRA's fixed in your latest RC and it looks like this one : https://jira.mongodb.org/browse/CSHARP-1645 – DevBackFlo Jul 06 '16 at 14:25
  • @CraigWilson : Hi Craig, by creating a sample and testing with version 2.1.1 and 2.2.4, I can say you were right. This has been fixed ! Thanks for your help! – DevBackFlo Jul 06 '16 at 14:31

1 Answers1

1

Problem fixed in the version 2.2.4 of the c# mongo db driver (probably with the bug https://jira.mongodb.org/browse/CSHARP-1645)

Thanks :)

DevBackFlo
  • 94
  • 8