在 RavenDB 中存储/检索动态数据
本文关键字:检索 动态 数据 存储 RavenDB | 更新日期: 2023-09-27 18:30:30
我正在使用RavenDB,需要存储动态数据,例如:
public class User {
public string Name;
public dynamic Data;
}
似乎我可以使用许多不同的类型,例如dynamic
,RavenJObject
,DynamicJsonObject
,ExpandoObject
,Dictionary<string, object>
,但我不知道有什么区别。
有人可以解释动态数据的选项吗?我不太关心查询,更关心易于存储和检索。
问题
这是交易,如果你有一个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 被序列化为/从字典序列化,仅此而已。