Как правильно моделировать слабо типизированные свойства в RavenDB - PullRequest
4 голосов
/ 01 февраля 2012

Я новичок в RavenDB и ищу рекомендации по правильному способу хранения свободно напечатанных данных.У меня есть тип со списком пар ключ / значение.Тип свойства value не известен во время разработки.

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

    public object Value { get; set; }
}

Когда я запрашиваю DescriptiveValue, который был сохранен со значением DateTime или Guid, десериализованным типом данных является строка.Числовые значения, похоже, сохраняют свои типы данных.

Существует ли элегантное решение для сохранения типа данных, или я должен просто хранить все значения в виде строк?Если я пойду по строковому маршруту, будет ли это ограничивать меня, когда я позже захочу отсортировать и отфильтровать эти данные (вероятно, по индексам?)

Я надеюсь, что это обычная проблема, которую легко решить, и я просто думаю,о проблеме неправильно.Ваша помощь очень ценится!

ОБНОВЛЕНИЕ : Результат этого модульного теста: Assert.AreEqual не удалось.Ожидается: <02.02.2012 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.

Ответы [ 2 ]

2 голосов
/ 01 февраля 2012

Абсолютно - это одна из сильных сторон баз данных без схем. Смотрите здесь: http://ravendb.net/docs/client-api/advanced/dynamic-fields

1 голос
/ 10 февраля 2012

Проблема в том, что сервер 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 мы также храним его тип. Позднее, возвращая значение, мы конвертируем его обратно в исходный тип.

После прохождения теста:

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);
            }
        }
    }
}
...