我是RavenDB的新手,正在寻找关于存储松散类型数据的正确方法的指导。我有一个带有键/值对列表的类型。value属性的类型在设计时未知。
public class DescriptiveValue
{
public string Key { get; set; }
public object Value { get; set; }
}
当我查询使用DateTime或Guid值保存的DescriptiveValue时,反序列化的数据类型为字符串。数值显示为保留其数据类型。
有没有一个优雅的解决方案来保留数据类型,或者我应该简单地将所有值存储为字符串?如果我走字符串路线,这会限制我以后想要排序和过滤这些数据(可能通过索引?)吗
我希望这是一个很容易解决的常见问题,但我只是错误地思考了这个问题。非常感谢您的帮助!
更新:此单元测试的输出为:Assert.AreEqual失败。应为:<2012年2月2日上午10:00:01(System.DateTime)>。实际:<2012-02-02T10:00:01.9047999(System.String)>.
[TestMethod]
public void Store_WithDateTime_IsPersistedCorrectly()
{
AssertValueIsPersisted<DateTime>(DateTime.Now);
}
private void AssertValueIsPersisted<T>(T value)
{
ObjectValuedAttribute expected = new ObjectValuedAttribute() { Value = value };
using (var session = this.NewSession())
{
session.Store(expected);
session.SaveChanges();
}
TestDataFactory.ResetRavenDbConnection();
using (var session = this.NewSession())
{
ObjectValuedAttribute actual = session.Query<ObjectValuedAttribute>().Single();
Assert.AreEqual(expected.Value, actual.Value);
}
}
我希望实际值是DateTime值。
绝对-这是无模式文档数据库的优势之一。请参见此处:http://ravendb.net/docs/client-api/advanced/dynamic-fields
问题是RavenDB服务器没有Value
类型的概念。当将对象发送到服务器时,Value
将被持久化为字符串,而当您稍后查询该文档时,反序列化程序不知道原始类型,因此Value
将被反序列化为字符串。
您可以通过将原始类型信息添加到ObjectValuedAttribute
:来解决此问题
public class ObjectValuedAttribute {
private object _value;
public string Key { get; set; }
public object Value {
get {
// convert the value back to the original type
if (ValueType != null && _value.GetType() != ValueType) {
_value = TypeDescriptor
.GetConverter(ValueType).ConvertFrom(_value);
}
return _value;
}
set {
_value = value;
ValueType = value.GetType();
}
}
public Type ValueType { get; private set; }
}
在Value
的setter中,我们还存储了它的类型。稍后,当获取值时,我们将其转换回原始类型。
以下测试通过:
public class CodeChef : LocalClientTest {
public class ObjectValuedAttribute {
private object _value;
public string Key { get; set; }
public object Value {
get {
// convert value back to the original type
if (ValueType != null && _value.GetType() != ValueType) {
_value = TypeDescriptor
.GetConverter(ValueType).ConvertFrom(_value);
}
return _value;
}
set {
_value = value;
ValueType = value.GetType();
}
}
public Type ValueType { get; private set; }
}
[Fact]
public void Store_WithDateTime_IsPersistedCorrectly() {
AssertValueIsPersisted(DateTime.Now);
}
private void AssertValueIsPersisted<T>(T value) {
using (var store = NewDocumentStore()) {
var expected = new ObjectValuedAttribute { Value = value };
using (var session = store.OpenSession()) {
session.Store(expected);
session.SaveChanges();
}
using (var session = store.OpenSession()) {
var actual = session
.Query<ObjectValuedAttribute>()
.Customize(x => x.WaitForNonStaleResults())
.Single();
Assert.Equal(expected.Value, actual.Value);
}
}
}
}