I have a problem while upserting to mongo db using the official C# driver.
public abstract class AggregateRoot
{
/// <summary>
/// All mongoDb documents must have an id, we specify it here
/// </summary>
protected AggregateRoot()
{
Id = ObjectId.GenerateNewId();
}
[BsonId]
public ObjectId Id { get; set; }
}
My entities already have the id-s but I had to create the mongo specific Id for it to work, as all the documents in a collection should have one. Now then I receive a new entity in my system a new Mongo Id is generated and I get the mongo cannot change _id of a document old exception. Is there some work-around?
Let me describe the design a bit. All the entities which would be stored as documents were inheriting from AggregateRoot which had the id generation in it. Every sub-document had its id generated automatically and I had no problem with this. The id in AggregateRoot was introduced to correct the problem when retrieving data from MongoCollection to List and the generation was introduced so the id-s are different. Now we can move that id generation to save methods because the new entity for update had a new id generation. But it would mean that every dev on the team must not forget generating id-s in repository which is risky. It would be nicer just to ignore the id than mapping from mongo if it is possible and not to have AggregateRoot class at all
You cannot update it but you can save a new id and remove the old id.
In MongoDB, each document stored in a collection requires a unique _id field that acts as a primary key.
MongoDB provides an automatic unique identifier for the _id field in the form of an ObjectId data type. For those that are familiar with MongoDB Documents you've likely come across the ObjectId data type in the _id field.
Yes, you can. BTW, uniqueness guaranteed by mongodb. Because _id field has a unique index by default.
Looks like you might be explicitly setting the Id
value for both inserts and updates. That's fine for inserts, all new objects need an _id
value, however for updates you're not allowed to change the value of _id
on an existing document after it's created.
Try not setting the Id
value at all. If you don't specify a value before inserting, the driver uses built-in IdGenerator
classes to generate a new _id value, so if it's an ObjectId type it'll use the ObjectIdGenerator
. Then both your inserts and updates work fine.
I've encountered similar problem. I wanted to upsert documents using official C# driver. I had a class like this:
public class MyClass
{
public ObjectId Id { get; set; }
public int Field1 { get; set; }
public string Field2 { get; set; }
}
In console I would write: db.collection.update({Field1: 3},{Field1: 3, Field2: "value"})
and it would work. In C# I wrote:
collection.Update(Query.EQ("Field1", 3),
Update.Replace(new MyClass { Field1 = 3, Field2 = "value" }),
UpdateFlags.Upsert);
and it didn't work! Because driver includes empty id in update statement and when I upsert second document with different value of Field1 exception E11000 duplicate key error index
is thrown (in this case Mongo tries to insert a document with _id that already exists in db).
When I generated _id by myself (like topic starter) I've encountered the same exception (mongo cannot change _id of a document
) on upserting objects with existing value of Field1.
Solution is to mark Id property by attribute [BsonIgnoreIfDefault]
(and not initialize it). In this case driver omits _id field in update statement and MongoDb generates Id if it necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With