我正在使用RavenDB&需要存储动态数据,如:
public class User {
public string Name;
public dynamic Data;
}
我似乎可以使用许多不同类型,例如dynamic
,RavenJObject
,DynamicJsonObject
,ExpandoObject
,Dictionary<string, object>
,但我不知道差异是什么。
有人可以解释动态数据的选项吗?我更少关心查询&amp;更多关于轻松存储的信息检索。
答案 0 :(得分:6)
这是交易,如果您有dynamic
属性,那么RavenDB 总是将其反序列化为RavenJObject
。例如:
public class User {
public dynamic Data = new ExpandoObject();
}
...
var user = new User();
user.Data.SomethingNew1 = "foo";
这看起来无害&amp;在创建用户时工作正常。但是当您加载用户时,RavenDB不知道dynamic
所需的类型,因此它使用RavenJObject
。您无法使用RavenJObject
动态创建属性(expando样式),因此失败:
var user = session.Find<User>(...);
user.Data.SomethingNew2 = "foo"; //compiles, but throws
使用ExpandoObject
并在序列化的属性中明确定义其类型。这让RavenDB(或我猜的JSON)知道你期待什么类型&amp;它不必猜测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':< / p>
List<string> keys = user.Data.Keys;
答案 1 :(得分:4)
对于所有这些,你的内存类型是什么并不重要。
对象,动态和DynamicJsonObject是相同的 - 就RavenDB而言。它给你一个 使用RavenJObject作为后端的动态实现。
RavenJObject实际上只是从服务器获得的值。
ExpandoObject和Dictionary序列化为/来自词典,是全部。