Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 417
Nathan Ridley Avatar asked Jun 22 '14 13:06

Nathan Ridley


People also ask

Can you use MongoDB with C#?

By developing with C# and MongoDB together one opens up a world of possibilities. Console, window, and web applications are all possible. As are cross-platform mobile applications using the Xamarin framework.

What is a MongoDB driver?

The official MongoDB Node. js driver allows Node. js applications to connect to MongoDB and work with data. The driver features an asynchronous API which allows you to interact with MongoDB using Promises or via traditional callbacks.

Is MongoDB paid?

MongoDB allows teams to choose their cloud provider of choice while providing database management that streamlines every aspect of database administration. It's easy to get started with MongoDB Atlas, and it's free.


2 Answers

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));
});
like image 184
BenCr Avatar answered Sep 20 '22 09:09

BenCr


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.

like image 45
Nathan Ridley Avatar answered Sep 17 '22 09:09

Nathan Ridley