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

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


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));});


Found the answer:

cm.IdMemberMap  .SetRepresentation(BsonType.ObjectId)  .SetIdGenerator(StringObjectIdGenerator.Instance);

This allows me to save as a native ObjectId and still have the Id represented in C# as a string. As a small gotcha, the id must be parsed before being queried upon:

public Account GetAccountById(string id){    return _accounts.FindOneById(ObjectId.Parse(id));}

Edit May 2015
Apparently the driver has changed since I wrote this answer. The other answer above is correct for newer versions, but this answer can still be referred to if using a legacy version of the driver.


In case you want that very same kind of mapping across a whole range of entities without the need to repeat yourself over and over again you might want to use a convention:

public class StringObjectIdIdGeneratorConventionThatWorks : ConventionBase, IPostProcessingConvention{    /// <summary>    /// Applies a post processing modification to the class map.    /// </summary>    /// <param name="classMap">The class map.</param>    public void PostProcess(BsonClassMap classMap)    {        var idMemberMap = classMap.IdMemberMap;        if (idMemberMap == null || idMemberMap.IdGenerator != null)            return;        if (idMemberMap.MemberType == typeof(string))        {            idMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance).SetSerializer(new StringSerializer(BsonType.ObjectId));        }    }}

...and then use it in lieu of all custom mappings:

ConventionPack cp = new ConventionPack();cp.Add(new StringObjectIdIdGeneratorConventionThatWorks());ConventionRegistry.Register("TreatAllStringIdsProperly", cp, _ => true);