Изменение "схемы" в RavenDB - PullRequest
       8

Изменение "схемы" в RavenDB

19 голосов
/ 24 января 2011

Просто для того, чтобы расширить свои знания, я начал изучать различные варианты NoSQL. Первый, который я посетил, - RavenDB, и это выглядит интересно. Я все еще пытаюсь сломать мое глубокое реляционное мышление вместе с типичными процедурами обслуживания СУБД.

В моей повседневной работе с Entity Framework мы выполняем процедуру сценариев изменений БД, обновления модели отображения EF и т. Д. Как это работает в NoSQL, особенно RavenDB? Как только приложение прошло жизнь, как можно вносить изменения в различные объекты POCO и т. Д. И развертывать его в рабочей среде? Что происходит с данными, хранящимися в старых классах POCO?

Я еще не углубился и не использовал Raven DB в гневе. Это может быть очевидно, как только я это сделаю, но мне хотелось бы знать заранее, чтобы я не загнал себя в угол.

Спасибо, D.

Ответы [ 4 ]

27 голосов
/ 24 января 2011

Они остаются как есть - свойства, которые больше не существуют, будут игнорироваться при загрузке (и будут потеряны при изменении), а отсутствующие свойства вернутся как ноль,

Рекомендуется использовать операции на основе набора для контроля данных с помощью объектной модели.

О, посмотри на меня, я сейчас на компьютере!

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

Важно признать, однако, что существует разница между схемой без схемы и структурой, в которой все ваши документы содержат свою собственную структуру (пары ключ / значение, обозначающие имя свойства и значение свойства).

Это делает его полезным для всего «просто начинающего» факта написания некоторого кода и сохранения ваших данных - но когда так легко обойтись, изменив структуру кода, может быть сложнее согласовать это с вашими уже сохраненными данными .

На данный момент появляется несколько стратегий:

  • Сделайте вашу структуру неизменной, как только вы сохраните данные, версируйте ваши классы
  • Разрешить изменение структуры, но использовать операции на основе набора для обновления данных для соответствия новой структуре
  • Разрешить изменение структуры и писать код для устранения несоответствий при загрузке данных

Третий вариант явно плохая, так как он приведет к неуправляемому коду, управление версиями ваших классов может сработать, если вы просто храните события или другие подобные данные, но на самом деле не подходит для большинства сценариев, так что вы остались со средним вариантом.

Я бы порекомендовал сделать именно это и следовать нескольким простым правилам в том же духе, что и при работе с предварительной схемой в реляционной базе данных.

  • Использование системы VCS для определения изменений между развернутыми версиями
  • Написание сценариев миграции, которые обновляются с одной версии на другую
  • Будьте осторожны с переименованием / удалением свойств - поскольку загрузка документа и сохранение документа приведет к потере данных, если эти свойства не существуют в новом документе

1037 * Etc. *

Надеюсь, это более полезно: -)

3 голосов
/ 18 декабря 2013

В этой статье Ayende описывается, как выполнить переход с 1 на версию 2 (в этом случае изменение свойства «Имя» на свойства «Имя» и «Фамилия».

http://ayende.com/blog/66563/ravendb-migrations-rolling-updates

Обычно слушатель зарегистрирован в хранилище документов:

documentStore.RegisterListener(new CustomerVersion1ToVersion2Converter())

Образец имплементации взят из статьи, упомянутой выше:

public class CustomerVersion1ToVersion2Converter : IDocumentConversionListener
{
    public void EntityToDocument(object entity, RavenJObject document, RavenJObject metadata)
    {
        Customer c = entity as Customer;
        if (c == null)
            return;

        metadata["Customer-Schema-Version"] = 2;
        // preserve the old Name property, for now.
        document["Name"] = c.FirstName + " " + c.LastName;
        document["Email"] = c.CustomerEmail;
    }

    public void DocumentToEntity(object entity, RavenJObject document, RavenJObject metadata)
    {
        Customer c = entity as Customer;
        if (c == null)
            return;
        if (metadata.Value<int>("Customer-Schema-Version") >= 2)
            return;

        c.FirstName = document.Value<string>("Name").Split().First();
        c.LastName = document.Value<string>("Name").Split().Last();
        c.CustomerEmail = document.Value<string>("Email");
    }
}
3 голосов
/ 24 января 2011

RavenDB сериализует ваши объекты .NET в формат JSON.Там нет схемы.

Если вы добавите некоторые объекты в базу данных, они будут сериализованы.Если вы добавите некоторые свойства в сериализуемый вами тип, у уже сохраненных объектов эти свойства будут отсутствовать.

2 голосов
/ 24 января 2011

Вы не столько не управляете схемами, сколько перемещаете его в свой код, чтобы никогда не было несоответствия между объектами в вашем коде и объектами в вашей базе данных.

Первая часть обработки изменений заключается в том, чтобы убедиться, что вы используете сериализатор, который может обрабатывать пропущенные / дополнительные значения - если поле не определено в данных, установите для него значение null.Если поле в данных не соответствует свойству вашего объекта, игнорируйте его.

Большинство изменений можно обрабатывать без каких-либо дополнительных действий - либо есть новое поле, и вам нужно иметь значение по умолчаниюдля существующих записей в любом случае, или есть старое поле, которое вас больше не волнует.

Для более сложных изменений, таких как переименование / объединение полей или изменение формата данных, добавьте новое поле в свой объект, не удаляястарые и ваш метод загрузки передает данные из старых полей.При сохранении записи она будет в новом формате.Этот код можно либо оставить на месте постоянно, обновляя данные по мере необходимости, либо вы можете настроить одноразовый процесс для вызова одного и того же кода для всех существующих объектов.Обратите внимание, что в отличие от сценария sql для этого типа обновления не требуется время простоя, даже если для работы с большим набором данных требуется много времени, поскольку код может обрабатывать как старые, так и новые форматы.

...