sil*_*ire 5 .net c# mongodb mongodb-csharp-2.0 mongodb-.net-driver
当我Id在 MongoDB 存储设置中重写派生类中的属性时,遇到了大问题。
我的所有数据模型继承的基类如下所示:
public abstract class DataModel
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public virtual string Id { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public DateTime Deleted { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后有一些使用upserts 的特定子数据模型。这需要我根据这个答案Id注释被覆盖的属性:[BsonIgnoreIfDefault]
public class ChildDataModel : DataModel
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
[BsonIgnoreIfDefault] // <---- need this for Upserts to work
public override string Id { get; set; }
... // child-specific properties
}
Run Code Online (Sandbox Code Playgroud)
但不幸的是它会导致这个错误:
“Namespace.ChildDataModel”类型的属性“Id”无法使用元素名称“_id”,因为它已被“Namespace.DataModel”类型的属性“Id”使用。
我尝试注册类映射,RootClass = true在基本模型上添加类型鉴别器,以及使用特殊[BsonKnownTypes(typeof(ChildDataModel), ...)]属性在基类上定义我的子数据模型,但无济于事。
我在这里做错了什么?
按照惯例,MongoDB 驱动程序尝试将所有命名的属性映射Id到_id类映射中。由于您有两个类,因此它会注册_id两次。如果是的话,更重要的BsonIgnoreIfDefault是可以正常工作Idnull这里不是,因为驱动程序会在您插入新文档时自动生成该值。
BsonIgnore如果你想_id在 MongoDB 中使用单个文件,可以使用它来解决这个问题
public class ChildDataModel : DataModel
{
[BsonRepresentation(BsonType.ObjectId)]
[BsonIgnore]
public override string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
将存储为:
{
"_id" : ObjectId("5cb5fe72e2a22b3848b6a1f6"),
"Created" : ISODate("2019-04-16T16:10:25.908Z"),
"Modified" : ISODate("2019-04-16T16:10:25.914Z"),
"Deleted" : ISODate("2019-04-16T16:10:25.914Z")
}
Run Code Online (Sandbox Code Playgroud)
BsonNoId或者,如果您想单独存储两个值,可以使用属性:
[BsonNoId]
public class ChildDataModel : DataModel
{
[BsonRepresentation(BsonType.ObjectId)]
public override string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
将:
{
"_id" : ObjectId("5cb5fecde2a22b3088ef731c"),
"Created" : ISODate("2019-04-16T16:11:56.810Z"),
"Modified" : ISODate("2019-04-16T16:11:56.822Z"),
"Deleted" : ISODate("2019-04-16T16:11:56.822Z"),
"Id" : ObjectId("5cb5fecde2a22b3088ef731c")
}
Run Code Online (Sandbox Code Playgroud)
然而从应用程序的角度来看它仍然是相同的值