使用官方C#驱动程序向mongo db上传时遇到问题。
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; }
}
我的实体已经拥有了id-s但我必须创建mongo特定的ID才能工作,因为集合中的所有文档都应该有一个。现在,我在系统中收到一个新实体,生成一个新的Mongo Id,我得到 mongo无法更改文档旧异常的_id。有一些解决方法吗?
让我来描述一下设计。所有实体都是 存储为文件的是继承自AggregateRoot的 id生成在其中。每个子文档都生成了id 自动,我对此没有任何问题。 AggregateRoot中的id 在从中检索数据时引入以纠正问题 MongoCollection to List和生成引入了id-s 是不同的。现在我们可以移动id生成来保存方法 因为更新的新实体有一个新的id生成。但它 意味着团队中的每个开发者都不能忘记生成id-s 在存储库中存在风险。忽略id会更好 如果有可能而不是从mongo映射 所有
的AggregateRoot类
答案 0 :(得分:62)
我遇到过类似的问题。 我想使用官方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,并且当我使用不同的Field1异常值E11000 duplicate key error index
向上插入第二个文档时(在这种情况下,Mongo尝试插入带有已存在于db中的_id的文档)。
当我自己生成_id时(比如主题启动器),我在遇到具有现有值Field1的对象时遇到了相同的异常(mongo cannot change _id of a document
)。
解决方案是按属性[BsonIgnoreIfDefault]
标记Id属性(而不是初始化)。在这种情况下,驱动程序省略update语句中的_id字段,MongoDb在必要时生成Id。
答案 1 :(得分:8)
您可能会明确为插入和更新设置Id
值。这对于插入来说很好,所有新对象都需要_id
值,但是对于更新,您不能在创建现有文档后更改_id
的值。
尝试根本不设置Id
值。如果在插入之前未指定值,则驱动程序使用内置的IdGenerator
类生成新的_id值,因此如果它是ObjectId类型,则它将使用ObjectIdGenerator
。然后你的插入和更新都可以正常工作。