9

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

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

看来我可以使用许多不同的类型,例如dynamic, RavenJObject, DynamicJsonObject, ExpandoObject, Dictionary<string, object>,但我不知道有什么区别。

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

4

2 回答 2

6

问题

这是交易,如果您有一个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 对象私有并为 . 创建一个 setter Data,但你明白了。

更多问题

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

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;
于 2012-04-09T16:00:41.723 回答
4

对于所有这些,你的内存类型是什么并不重要。

object、dynamic 和 DynamicJsonObject 是一回事——就 RavenDB 而言。它为您提供了一个使用 RavenJObject 作为后端的动态实现。

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

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

于 2012-04-09T06:30:23.340 回答