在 RavenDB 中存储/检索动态数据

本文关键字:检索 动态 数据 存储 RavenDB | 更新日期: 2023-09-27 18:30:30

我正在使用RavenDB,需要存储动态数据,例如:

public class User {
    public string Name;
    public dynamic Data;
}

似乎我可以使用许多不同的类型,例如dynamicRavenJObjectDynamicJsonObjectExpandoObjectDictionary<string, object>,但我不知道有什么区别。

有人可以解释动态数据的选项吗?我不太关心查询,更关心易于存储和检索。

在 RavenDB 中存储/检索动态数据

问题

这是交易,如果你有一个dynamic属性,那么RavenDB将始终将其反序列化为RavenJObject。 例如:

public class User {
    public dynamic Data = new ExpandoObject();
}
...
var user = new User();
user.Data.SomethingNew1 = "foo";

这看起来无害,并且在您创建用户时工作正常。但是当你加载用户时,RavenDB不知道你想要什么类型dynamic所以它使用RavenJObject。您无法使用 RavenJObject 动态创建属性(展开样式),因此此操作失败:

var user = session.Find<User>(...);
user.Data.SomethingNew2 = "foo"; //compiles, but throws

我的解决方案

使用ExpandoObject并在序列化的属性中显式定义其类型。 这让RavenDB(或我猜的JSON)知道你期望什么类型,它不必猜测RavenJObject。然后,若要保持语法魔力,请使用动态访问器包装属性。

public class User {
    public ExpandoObject _Data = new ExpandoObject();
    public dynamic Data {
        get { return _Data; }
    }
}

有一些方法可以使expando对象私有并为Data创建一个setter,但你明白了。

更多问题

更新:不幸的是,此解决方案暴露了更多问题。假设您在动态数据中存储了一个字符串列表:

user.Data.Keys = new List<String>{"a","b","c"};

序列化/反序列化后,JSON/Raven 再次不知道您期望的类型。因此,如果您尝试此操作(见下文),那么它会编译,但会出现运行时异常 无法将类型"Raven.Abstractions.Linq.DynamicList"隐式转换为"System.Collections.Generic.List"

List<string> keys = user.Data.Keys;

对于所有这些,您的内存类型并不重要。

object,dynamic和DynamicJsonObject是一回事 - 就RavenDB而言。它给你一个使用RavenJObject作为后端的动态实现。

RavenJObject实际上只是您从服务器获得的值。

ExpandoObject 和 Dictionary 被序列化为/从字典序列化,仅此而已。