Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing a Dictionary with polymorphic values in mongoDB using C#

Let us say we have a key with values which are polymorphic in their sense. Consider the next sample project:

public class ToBeSerialized
{
    [BsonId]
    public ObjectId MongoId;
    public IDictionary<string, BaseType> Dictionary;
}

public abstract class BaseType
{
}

public class Type1 : BaseType
{
    public string Value1;
}

public class Type2:BaseType
{
    public string Value1;
    public string Value2;
}


internal class Program
{
    public static void Main()
    {
        var objectToSave = new ToBeSerialized
                               {
                                   MongoId = ObjectId.GenerateNewId(),
                                   Dictionary = new Dictionary<string, BaseType>
                                                    {
                                                        {"OdEd1", new Type1 {Value1="value1"}},
                                                        {
                                                            "OdEd2",
                                                            new Type1 {Value1="value1"}
                                                            }
                                                    }
                               };
        string connectionString = "mongodb://localhost/Serialization";
        var mgsb = new MongoUrlBuilder(connectionString);
        var MongoServer = MongoDB.Driver.MongoServer.Create(mgsb.ToMongoUrl());
        var MongoDatabase = MongoServer.GetDatabase(mgsb.DatabaseName);
        MongoCollection<ToBeSerialized> mongoCollection = MongoDatabase.GetCollection<ToBeSerialized>("Dictionary");
        mongoCollection.Save(objectToSave);

        ToBeSerialized received = mongoCollection.FindOne();
    }
}

Sometimes when I try to deserialize it, I get deserialization errors like "Unknown discriminator value 'The name of concrete type'". What am I doing wrong? If every value stores a _t why cannot it map it correctly?

like image 282
Yurii Hohan Avatar asked Nov 15 '11 14:11

Yurii Hohan


2 Answers

Driver should know about all discriminators to deserialize any class without errors. There are two ways to do it:

1.Register it globally during app start:

BsonClassMap.RegisterClassMap<Type1>();
BsonClassMap.RegisterClassMap<Type2>();

2.Or though the BsonKnownTypes attibute:

[BsonKnownTypes(typeof(Type1), typeof(Type2)]
 public class BaseType
 {

 }

If you will use #1 or #2 your deserialization will work correctly.

like image 137
Andrew Orsich Avatar answered Sep 29 '22 00:09

Andrew Orsich


You have to register which types inherit from BaseClass before attempting to deserialize them. This will happen automatically if you serialize first, which is probably why the error occurs only sometimes.

You can register derived types using an attribute:

[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(DerivedType1), typeof(DerivedType2))]
public class BaseClass { ... }

public class DerivedType1 : BaseClass { ... }
like image 35
mnemosyn Avatar answered Sep 29 '22 01:09

mnemosyn