在Mongo DB中升级和Id问题

使用官方C#驱动程序向mongo db发送插件时遇到问题。

public abstract class AggregateRoot { ///  /// All mongoDb documents must have an id, we specify it here ///  protected AggregateRoot() { Id = ObjectId.GenerateNewId(); } [BsonId] public ObjectId Id { get; set; } } 

我的实体已经拥有了id-s但我必须创建mongo特定的ID才能使用,因为集合中的所有文档都应该有一个。 现在我在我的系统中收到一个新实体,生成一个新的Mongo Id,我得到的mongo无法更改文件旧exception的_id 。 有一些解决方法吗?

让我来描述一下设计。 将作为文档存储的所有实体都inheritance自AggregateRoot,其中包含id生成。 每个子文档都自动生成了id,我对此没有任何问题。 引入AggregateRoot中的id是为了在从MongoCollection到List检索数据时纠正问题,并且引入了生成,因此id-s不同。 现在我们可以移动id生成来保存方法,因为更新的新实体有一个新的id生成。 但这意味着团队中的每个开发人员都不能忘记在存储库中生成id-s,这是有风险的。 如果可能的话,忽略id而不是mongo的映射会更好,而根本就没有AggregateRoot类

看起来您可能会明确设置插入和更新的Id值。 这对插入来说很好,所有新对象都需要_id值,但是对于更新,在创建现有文档后不允许更改现有文档的_id值。

尽量不要设置Id值。 如果在插入之前未指定值,则驱动程序使用内置的IdGenerator类生成新的_id值,因此如果它是ObjectId类型,则它将使用ObjectIdGenerator 。 然后你的插入和更新工作正常。

我遇到过类似的问题。 我想使用官方C#驱动程序来插入文档。 我有一个这样的课:

 public class MyClass { public ObjectId Id { get; set; } public int Field1 { get; set; } public string Field2 { get; set; } } 

在控制台中我会写: db.collection.update({Field1: 3},{Field1: 3, Field2: "value"}) ,它会工作。 在C#中我写道:

 collection.Update(Query.EQ("Field1", 3), Update.Replace(new MyClass { Field1 = 3, Field2 = "value" }), UpdateFlags.Upsert); 

它不起作用! 因为驱动程序在update语句中包含空id,当我使用不同的Field1exception值插入第二个文档时,会抛出E11000 duplicate key error index (在这种情况下,Mongo会尝试插入一个已经存在于db中的_id文档)。

当我自己生成_id(比如主题启动器)时,我在遇到具有现有值Field1的对象时遇到了相同的exception( mongo cannot change _id of a document )。

解决方案是按属性[BsonIgnoreIfDefault]标记Id属性(而不是初始化它)。 在这种情况下,驱动程序省略update语句中的_id字段,MongoDb在必要时生成Id。