0

I'm seeking community guidance regarding the cost of upgrading our existing Mongo framework to use the new 2.0 drivers.

Using the now legacy Mongo C# drivers (1.8 & 1.9), we built a framework for reading & writing our collections to MongoDB. The collections are named after specific types - for example a type of "AnimalView" is written to a collection "AnimalView".

When writing the collection, each document is accompanied by a "container" object that is typed, i.e. MongoDbContainer. "Keys" are a Guid or an object constructed using a Guid, making it pretty straightforward to do CRUD operations (with either the legacy or new Mongo drivers):

public class MongoDbContainer<TKey, TEntity> : IMongoWriter<TKey, TEntity>
{
    public void Add (TKey key, TEntity entity)
    {
        var server = mongoClient.GetServer();
        var db = server.GetDatabase(databaseName);
        var collection = db.GetCollection<TEntity>(typeof(TEntity).Name);
        collection.Insert(entity);
    }
}

public class AnimalWriter
{
    IMongoWriter<AnimalId, AnimalView> writer;
    public AnimalWriter(IMongoWriter<AnimalId, AnimalView> writer)
    {
        this.writer = writer;
    }
    public void CreateAnimal(AnimalData data)
    {
        var view = new AnimalView {… assign from data…};
        writer.Add(data.AnimalId, view);
    }
}

It is apparent that this framework will be relatively straightforward to convert to the new driver. However, we also have a couple of other types of entities that we use as Indexes:

public class Singleton<T>
{
    public string Id { get; set; }
    public T Value { get; set; }
} 

public class Chunk<T>
{
    public byte Id { get; set; }
    public T Value {get; private set; }
}

The "Singleton" class is written to a Mongo collection called "singletons", and is retrieved from Mongo as follows:

public MongoCollection<BsonDocument> GetSingletonsCollection()
{
    var server = mongoClient.GetServer();
    var db = server.GetDatabase(databaseName);
    var collection = db.GetCollection("singletons");
}

This is where converting to the new driver starts to break down. The TEntity for a singleton is the type of the Singleton Value property. So to retrieve a Singleton collection for update, it is no longer sufficient to have a as the value type of the ICollection because there is no guarantee that the type TEntity will cleanly map to a BsonDocument.

Legacy Method:

public void AddSingleton(TEntity entity)
{
    var collection = GetSingletonsCollection();
    var singleton = new Singleton<TEntity>(entity);
    collection.Insert(singleton);
}

The Legacy method did not need to know that the type of of the collection was anything more than <Singleton<BsonDocument>>. All of the mapping and conversion was handled by the driver. However the new insert method has an issue - the collection is of type <Singleton<BsonDocument>>, but the document to insert is a <Singleton<MyClass>>, so

collection.InsertOneAsync(entity);

doesn't work because entity is not the same type as the collection. I have tried converting "entity" to a BsonDocument, but on some classes that conversion fails, especially when the class contains a dictionary or other types.

This problem is compounded with the "Chunk" class. Unlike singletons, Chunks are written to Mongo collections bearing the name of the "Value" property. However, the Id is a "byte" and cannot be converted to Bson as such. So in addition to the same issues with generics that we have with the Singleton class, we now have to find a way to properly map the ids.

I have tried working with reflection to create generics with some success, but am limited in what I can do, because we have to discover everything - methods and properties - via reflection. Additionally, the Builder extension methods (Filter, Update & etc) are not available (or I don't know how to use them) because they are not discoverable through reflection.

I apologize for the length of this question and lack of a specific "how-to", but it was necessary to properly describe our issues. We would like to upgrade to MongoDB.Driver 2.0, but the cost may be prohibitive given the amount of rewrite we may have to do. And while staying with the legacy 1.x drivers is attractive because it continues to work, we are worried about their being desupported, in addition to not being able to take advantage of new features introduced in Mongo going forward.

Is it premature to upgrade to MongoDB 3.0 and use the 2.0 drivers (are further API changes in the works or is what is baked into 2.0 pretty firm at this point)? Am I misguided in my approach of trying to keep our existing, non-generic framework in place?

Thank you very much in advance for any direction we can provide.

Kerry
  • 41
  • 3
  • I really don't understand the problem. Singletons that can be serialized? Huh? Reflection? But the driver uses reflection already... Why would you use a `byte` as an id? Why can't it be converted to a BsonValue and why would you ever need to do that? I'd recommend asking a set of *much* smaller, specific questions. I guess you could have converted the entire application in less time it took to write the question, it's not that big a deal. – mnemosyn May 07 '15 at 16:17
  • @mnemosyn - Your reply actually provided some help when you asked why a byte couldn't be converted to a BsonValue. However, it took some time to parse through the other condescending remarks to see what was causing issues. I understand that my post was lengthy, and I did spend quite a bit of time crafting it, but not as much as I did vetting it with other developers. Responses like yours discourage people from asking questions and detract from the usefulness of Stack Exchange as a whole. – Kerry May 08 '15 at 19:32
  • @Kerry I'd step soft-footed from this point. That guy not only knows what he is talking about, being correct this time again, he has read some essentials you might have missed until now. You might want to read [How do I ask a good question](http://stackoverflow.com/help/how-to-ask), which enhances the probability for getting a useful answer _drastically_. You might find [ESR](https://en.m.wikipedia.org/wiki/Eric_S._Raymond)'s excellent essay [How To Ask Questions The Smart Way](http://catb.org/~esr/faqs/smart-questions.html) helpful, too. – Markus W Mahlberg May 10 '15 at 07:51

1 Answers1

1

Ultimately, the problem lay in changes made to BSON Serialzation for Dictionaries. Several of the classes that were implemented as "singletons" contained Dictionaries to further index information, and the serialization was choking there.

By applying the changes in suggested in the post BSON Serialization Exceptions when Serializing a Dictionary the issue was resolved. The error messages did not manifest themselves directly as they were included in the Task.Exception property resulting from the call to InsertOneAsync.

Kudos to @i3arnon for a well-written post.

Community
  • 1
  • 1
Kerry
  • 41
  • 3