How to properly model weakly typed properties in RavenDB

I am new to RavenDB and looking for guidance on the correct way to store data printed from data. I have a type with a list of key / value pairs. The type of the value property is unknown at design time.

public class DescriptiveValue { public string Key { get; set; } public object Value { get; set; } } 

When I request a DescriptiveValue that was saved using DateTime or Guid Value, the deserialized data type is a string. Numeric values ​​retain their data types.

Is there an elegant solution to save a data type or just save all values ​​as strings? If I go along the string route, it will limit me when I later want to sort and filter this data (probably through indexes?)

I hope this is a common problem that can be easily solved, and I just think the problem is wrong. Your help is much appreciated!

UPDATE : The result of this unit test is: Assert.AreEqual failed. Expected: <2/2/2012 10:00:01 AM (System.DateTime)>. Actual: <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); } } 

I would expect the actual value of DateTime.

+4
source share
2 answers

The problem is that the RavenDB server has no concept of type Value . When an object is sent to the server, Value saved as a string, and the next time this document is requested, the deserializer does not know about the original type, so Value deserialized as a string.

You can solve this problem by adding the initial type information to the 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; } } 

In the Value installer, we also save its type. Later, returning the value, we will convert it back to the original one.

After passing the test:

 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); } } } } 
+1
source

Absolutely - this is one of the strongest uncertificated databases. See here: http://ravendb.net/docs/client-api/advanced/dynamic-fields

+2
source

Source: https://habr.com/ru/post/1394090/


All Articles