Persist Objects Using Mongo C # Driver

I have the following class hierarchy

[BsonKnownTypes(typeof(MoveCommand))] public abstract class Command : ICommand { public abstract string Name { get; } public abstract ICommandResult Execute(); } public class MoveCommand : Command { public MoveCommand() { this.Id = ObjectId.GenerateNewId().ToString(); } [BsonId] public string Id { get; set; } public override string Name { get { return "Move Command"; } } public override ICommandResult Execute() { return new CommandResult { Status = ExecutionStatus.InProgress }; } } 

if I save the command as follows:

  Command c = new MoveCommand(); MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c); 

and then query the DB, I don’t see the derived properties being preserved.

{"_id": "4df43312c4c2ac12a8f987e4", "_t": "MoveCommand"}

I would suggest that the Name property is the key in the document. What am I doing wrong?

Also, is there a way to avoid using the BsonKnowTypes attribute in the base class to preserve existing instances? I do not see why the base class should know about derived classes. This is a poor OO design and is coerced into my class hierarchy by the BSON library. Did I miss something?

+4
source share
1 answer

1. The Name property has not been stored in the database since it is not configured. Serializers do not serialize properties that are not set (because if the serializer serializes such a property, it cannot deserialize it back). Therefore, if you want to serialize the Name property, just add a fake setter (in ICommand you need to add it as well):

  public override string Name { get { return "Move Command"; } set{} } 

2. If you do not want to use the BsonKnownTypes attribute, there is another way to notify the serializer of the types of knowledge that it may encounter during deserialization. Just register cards once, in case of application launch:

 BsonClassMap.RegisterClassMap<MoveCommand>(); //all other inherited from ICommand classes need register here also 

Therefore, you must use either the attribute or the KnownTypes attribute or the BsonClassMap register or register for each polymorphic class, otherwise you will receive an "unknown descriminator" error message during deserialization:

  var commands = col.FindAllAs<ICommand>().ToList(); 

3 You said:

This is a poor OO design and is forced into my class hierarchy by the BSON library.

In any case, even without KnownTypes assign your code using Bson lib via the BsonId attribute. If you want to avoid this, you can:

  BsonClassMap.RegisterClassMap<MoveCommand>(cm => { cm.AutoMap(); cm.SetIdMember(cm.GetMemberMap(c => c.Id)); }); 

So now you can remove the link to Mongodb.Bson lib from your lib domain code.

+6
source

All Articles