ijjo
ijjo

Reputation: 525

how to read back out the auto generated ID from mongo after insertion using official c# driver?

after you insert a new document into mongodb via the official c# driver, how to you immediately read back the generated _id so I can use it as a "foreign" key to other collections? i know in sql server i can immediately read back the identity column value for the newly inserted row, so i need the similar functionality in mongodb.

since the _id generated by mongo isn't an actual member of the object, assume you need to do something with the generic bsondocument?

Upvotes: 4

Views: 4054

Answers (5)

kelloti
kelloti

Reputation: 8941

Like the other answers here say, IDs are assigned client-side. Something you can do is create a default value convention that generates a new ID during insert if it hasn't been set yet.

public class DefaultValueConvention : MongoDB.Bson.Serialization.Conventions.IDefaultValueConvention
{
    public object GetDefaultValue(MemberInfo memberInfo)
    {
        var type = memberInfo.MemberType == MemberTypes.Property
                       ? ((PropertyInfo) memberInfo).PropertyType
                       : ((FieldInfo) memberInfo).FieldType;

        if (type.IsSubclassOf(typeof(ObjectId)))
            return ObjectId.GenerateNewId();
        else
            return null;
    }
}

And setup the driver to use this convention:

var profile = new ConventionProfile();
profile.SetDefaultValueConvention(new DefaultValueConvention());
BsonClassMap.RegisterConventions(profile, x => x.FullName.StartsWith("ConsoleApplication"));

So now you can create an object & persist it in 2 lines:

var animal = new Animal {Name = "Monkey", PercentDeviationFromHumans = 2.01};
db["animals"].Save(animal);

Actually, with the most recent driver you don't even need to set the default value convention, it already has this behavior OOTB. Regardless, conventions are underused in mongo.

Upvotes: 0

Tyler Brock
Tyler Brock

Reputation: 30136

You can do an upsert with the findAndModify command to achieve this same effect with less work than going through generating your own id's. (Why bother, there is a very good reason 10gen decided on the sceme that is used -- it enables easy sharding)

The findAndModify command lets you find or upsert (create if it doesn't exist) a document and return that same document.

The general form is as follows:

db.runCommand( { findAndModify : <collection>, <options> } )

You can read more about it here.

You would want to use the new in addition to the upsert option so that you get back the newly created object.

Upvotes: 2

Gates VP
Gates VP

Reputation: 45277

In most drivers the _id field is actually generated on the client side before going to the server. MongoDB does not use an "auto-increment" ID, so you can actually generate a random ID and tell the server "use this".

In C# the code looks like this:

var id = ObjectId.GenerateNewId();

So you can create a BSON document and simply save it:

var toSave = new BsonDocument {
    { "_id", ObjectId.GenerateNewId() },
    { "data", "my data" }
};
db.collection.Save(toSave);

However, by default, when you .Save() a document this will update the _id field. So you can generally just save the BSONDocument (or BSONSerializable class) and then read it back.

Note that there is a specification called DBRef that helps simplify the implementation of "Foreign Keys". The docs are here, in C# you will want to look at the DBRef class.

Upvotes: 0

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230276

In MongoDB, ids are (usually) generated on client side. And you can generate one yourself, using appropriate driver call, put in into document and it'll get saved.

I didn't work with C# driver, but Ruby driver does all the work for me.

ruby-1.9.3-p0 :027 >   obj = coll.insert({'foo' => 'bar'})
 => BSON::ObjectId('4ef15e7f0ed4c00272000001') 
ruby-1.9.3-p0 :030 > coll.find.to_a
 => [{"_id"=>BSON::ObjectId('4ef15e7f0ed4c00272000001'), "foo"=>"bar"}] 

This is how I can make a new ID

ruby-1.9.3-p0 :039 >   newid = BSON::ObjectId.new
 => BSON::ObjectId('4ef15f030ed4c00272000002') 
ruby-1.9.3-p0 :040 > coll.insert({_id: newid, test: 'test'})
 => BSON::ObjectId('4ef15f030ed4c00272000002') 
ruby-1.9.3-p0 :041 > coll.find.to_a
 => [{"_id"=>BSON::ObjectId('4ef15e7f0ed4c00272000001'), "foo"=>"bar"},     {"_id"=>BSON::ObjectId('4ef15f030ed4c00272000002'), "test"=>"test"}] 

Upvotes: 1

nilskp
nilskp

Reputation: 3127

If you need the _id, you can generate it yourself and set it manually on the document.

Upvotes: 1

Related Questions