Reputation: 174
As it known, mongoDb default driver doesn't support automatic integer Id generation. I spent 2 days for thinking how to implement my own id generator of unique integer values. So, how to make it ?
Upvotes: 10
Views: 15526
Reputation: 7025
I would use a GUID as primary key instead of an integer. It has mainly two benefits
It is thread safe
You don't need to worry about calculating next ID.
Code needed to get new ID is pretty easy
Guid.NewGuid()
Check this useful article in CodingHorror that explains pros and cons of using GUID over classical integer IDs.
Upvotes: 3
Reputation: 38529
A late answer, but I thought I'd post this:
https://github.com/alexjamesbrown/MongDBIntIdGenerator
I made a start on an incremental ID generator.
Note - this is far from ideal, and not what mongodb was intended for.
Upvotes: 1
Reputation: 4493
Its not good practice to make auto increment Id in MongoDB, as I will hurt in scaling your server, but If you want to make auto increment value it is not advisable to iterate your collection, Instead make a separate table (sequence like concept) and read value from there and increment it using findAndModify. It will be unique per table.
> db.counters.insert({_id: "userId", c: 0});
> var o = db.counters.findAndModify(
... {query: {_id: "userId"}, update: {$inc: {c: 1}}});
{ "_id" : "userId", "c" : 0 }
> db.mycollection.insert({_id:o.c, stuff:"abc"});
> o = db.counters.findAndModify(
... {query: {_id: "userId"}, update: {$inc: {c: 1}}});
{ "_id" : "userId", "c" : 1 }
> db.mycollection.insert({_id:o.c, stuff:"another one"});
Upvotes: 7
Reputation: 174
Something like that:
public class UniqueIntGenerator : IIdGenerator
{
private static UniqueIntGenerator _instance;
public static UniqueIntGenerator Instance { get { return _instance; } }
static UniqueIntGenerator()
{
_instance = new UniqueIntGenerator();
}
public object GenerateId(object container, object document)
{
var cont = container as MongoCollection;
if (cont == null)
return 0;
var type = cont.Settings.DefaultDocumentType;
var cursor = cont.FindAllAs(type);
cursor.SetSortOrder(SortBy.Descending("_id"));
cursor.Limit = 1;
foreach (var obj in cursor)
return GetId(obj) + 1;
return 1;
}
private int GetId(object obj)
{
var properties = obj.GetType().GetProperties();
var idProperty = properties.Single(y => y.GetCustomAttributes(typeof(BsonIdAttribute), false).SingleOrDefault() != null);
var idValue = (int)idProperty.GetValue(obj, null);
return idValue;
}
public bool IsEmpty(object id)
{
return default(int) == (int)id;
}
}
Upvotes: -4