Search code examples
c#mongodbmongodb-.net-driver

MongoDB C# Driver - how to store _id as ObjectId but map to string Id property?


I'm having trouble getting my model to represent an entity's Id property as a string but have it auto-generated and represented internally by MongoDb as a native ObjectId.

class Account
{
    public string Id { get; set; }
    ...
}

class AccountStore
{
    static AccountStore()
    {
        BsonClassMap.RegisterClassMap<Account>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);

            // map Id property here
        });
    }

    public void Save(Account account)
    {
        _accounts.Save(account);
    }
}

For the line // map Id property here in the above code, I've tried numerous different ways of configuring the Id mapping and none have worked. The ways I have tried, and the associated exceptions that are thrown when I call the Save method, are:

// Exception: No IdGenerator found.
cm.IdMemberMap
  .SetRepresentation(BsonType.ObjectId);

// Exception: No IdGenerator found.
cm.IdMemberMap
  .SetRepresentation(BsonType.String);

// Exception: Unable to cast object of type 'MongoDB.Bson.ObjectId' to type 'System.String'.
cm.IdMemberMap
  .SetRepresentation(BsonType.ObjectId)
  .SetIdGenerator(ObjectIdGenerator.Instance);

// Exception: Unable to cast object of type 'MongoDB.Bson.ObjectId' to type 'System.String'.
cm.IdMemberMap
  .SetRepresentation(BsonType.String)
  .SetIdGenerator(ObjectIdGenerator.Instance);

// Exception: Unable to cast object of type 'MongoDB.Bson.ObjectId' to type 'System.String'.
cm.IdMemberMap
  .SetIdGenerator(ObjectIdGenerator.Instance);

What am I doing wrong? I thought this was a standard use case for id handling?


Solution

  • This has changed, I'm using the latest 1.x driver (Nuget package <package id="mongocsharpdriver" version="2.0.0" targetFramework="net45" />) and instead of using SetRepresentation you set the serialiser.

    public class RegistrationAttempt
    {
        public string AttemptId { get; set; }
    }
    
    BsonClassMap.RegisterClassMap<RegistrationAttempt>(cm =>
    {
        cm.AutoMap();
        cm.MapIdProperty(c => c.AttemptId)
            .SetIdGenerator(StringObjectIdGenerator.Instance)
            .SetSerializer(new StringSerializer(BsonType.ObjectId));
    });