使用 Mongo C# 驱动程序保留派生对象

发布于 2024-11-14 19:40:33 字数 1033 浏览 4 评论 0原文

我将得到以下类层次结构

[BsonKnownTypes(typeof(MoveCommand))]
public abstract class Command : ICommand
{
    public abstract string Name
    {
        get;
    }

    public abstract ICommandResult Execute();
}
    public class MoveCommand : Command
{
    public MoveCommand()
    {
        this.Id = ObjectId.GenerateNewId().ToString();
    }

    [BsonId]
    public string Id { get; set; }

    public override string Name
    {
        get { return "Move Command"; }
    }

    public override ICommandResult Execute()
    {
        return new CommandResult { Status = ExecutionStatus.InProgress };
    }
}

如果我像这样保存命​​令,

 Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);

:然后查询数据库,我看不到派生属性仍然存在。

{ "_id" : "4df43312c4c2ac12a8f987e4", "_t" : "MoveCommand" }

我希望 Name 属性作为文档中的键。 我做错了什么?

另外,有没有办法避免在基类上使用 BsonKnowTypes 属性来持久保存派生实例?我不明白为什么基类需要了解派生类。这是糟糕的 OO 设计,并且 BSON 库强加在我的类层次结构上。我在这里错过了什么吗?

I have the following class hierarchy

[BsonKnownTypes(typeof(MoveCommand))]
public abstract class Command : ICommand
{
    public abstract string Name
    {
        get;
    }

    public abstract ICommandResult Execute();
}
    public class MoveCommand : Command
{
    public MoveCommand()
    {
        this.Id = ObjectId.GenerateNewId().ToString();
    }

    [BsonId]
    public string Id { get; set; }

    public override string Name
    {
        get { return "Move Command"; }
    }

    public override ICommandResult Execute()
    {
        return new CommandResult { Status = ExecutionStatus.InProgress };
    }
}

if I save the command like so:

 Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);

and then query the DB, I don't see the derived properties persisted.

{ "_id" : "4df43312c4c2ac12a8f987e4", "_t" : "MoveCommand" }

I would expect a Name property as a key in the document.
What am I doing wrong?

Also, is there a way to avoid having a BsonKnowTypes attribute on the base class for persisting derived instances? I don't see the why a base class needs to know about derived classes. This is bad OO design and is being forced on my class hierarchy by the BSON library. Am I missing something here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悸初 2024-11-21 19:40:33

1.Name属性没有保存到数据库中,因为它没有setter。序列化程序不会序列化没有设置器的属性(因为如果序列化程序序列化此类属性,它将无法将其反序列化回来)。因此,如果你想序列化 Name 属性,那么只需添加假设置器(到 ICommand 中也需要添加它):

  public override string Name
  {
    get { return "Move Command"; }
    set{}
  }

2.如果你不想使用 BsonKnownTypes 属性,还有另一个通知序列化程序在反序列化过程中可能遇到的已知类型的方法。只需在应用程序启动事件上注册一次映射:

BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also

因此您应该使用或 KnownTypes 属性或为每个多态类注册 ​​BsonClassMap ,否则您将在反序列化期间收到“未知鉴别器”错误:

  var commands = col.FindAllAs<ICommand>().ToList();

3 你说:

这是糟糕的 OO 设计,正在被
强行强加于我的阶级层次结构
BSON 库。

即使没有 KnownTypes,也可以通过 BsonId 属性使用 Bson lib 来分配代码。
如果您想避免它,您可以:

   BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
        cm.AutoMap();
        cm.SetIdMember(cm.GetMemberMap(c => c.Id));
    });

现在您可以从域代码库中删除对 Mongodb.Bson lib 的引用。

1.Name property was not saved into database because it haven't setter. Serializers not serialize properties that's haven't setters (because if serializer serialize such property it will not able deserialize it back). So if you want serialize Name property then just add fake setter(into ICommand need to add it also):

  public override string Name
  {
    get { return "Move Command"; }
    set{}
  }

2.If you don't want use BsonKnownTypes attribute there is another way to notify serializer about know types it might encounter during deserialization. Just Register maps once, on app start event:

BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also

So you should use or KnownTypes attribute or register BsonClassMap for each polymorphic class, otherwise you will get 'unknown descriminator' error during deserializtion:

  var commands = col.FindAllAs<ICommand>().ToList();

3 You said:

This is bad OO design and is being
forced on my class hierarchy by the
BSON library.

In any way even without KnownTypes atribute your code using Bson lib through BsonId attribute.
If you want avoid it you can:

   BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
        cm.AutoMap();
        cm.SetIdMember(cm.GetMemberMap(c => c.Id));
    });

So now you can remove reference to Mongodb.Bson lib from your domain code lib.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文