MongoDB:子类的 ID 和属性被覆盖的问题

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), ...)]属性在基类上定义我的子数据模型,但无济于事。

我在这里做错了什么?

mic*_*ckl 5

按照惯例,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)

然而从应用程序的角度来看它仍然是相同的值