Изменение «схемы» в Ravendb
Вопрос
Просто для интереса расширения моих знаний, я начал искать различные варианты NOSQL. Первый, который я посетил, это Ravendb, и это выглядит интересно. Я все еще пытаюсь сломать свое глубоко укоренившееся реляционное мышление, а также типичные процедуры обслуживания RDBMS.
В моей повседневной работе с структурой сущности мы проходим процедуру сценариев сценариев, обновляя модель картирования EF и т. Д. Как это работает в NOSQL, особенно Ravendb? Как только приложение ушло с жизнью, как можно внести изменения в различные объекты Poco и т. Д. И развернуть его в производстве? Что происходит с данными, хранящимися в старых классах POCO?
Я еще не углубил или использовал Raven DB в гневе. Это может быть очевидно, как только я это сделаю, но хотел бы узнать заранее, чтобы я не кодировался в угол.
Спасибо д.
Решение
Они остаются такими, какие они есть - свойства больше не существуют, будут игнорироваться при загрузке (и потеряны при переменах), и пропущенные свойства вернутся как нулевые,
Рекомендую использовать установленные операции, чтобы контролировать данные с объектной моделью.
О, посмотри на меня, я сейчас на компьютере!
Правильно, в основном, при переезде в хранилище документов вы правы, признаете, что вы теряете некоторую функциональность и получите некоторую свободу в том смысле, что в базе данных у вас есть схема с предварительной схемой и пытается загрузить данные, которые не соответствуют этой схеме привести к ошибке.
Однако важно признать, что существует разница между без схемы и без структуры, поскольку все ваши документы содержат свою собственную структуру (пары ключей/значения, обозначающие имя свойства и значение свойства).
Это делает его полезным для всего «просто попадания» фактора написания некоторого кода и упорства ваших данных - но, когда так легко обходить структуру кода, может быть сложнее примирить это с вашими уже сохраняющимися данными.
Несколько стратегий представлены на данный момент:
- Сделайте свою структуру неизбежной после
- Разрешить изменение структуры, но используйте операции на основе наборов для обновления данных для соответствия новой структуре
- Разрешить изменение структуры и записать код для борьбы с несоответствиями при загрузке данных
Третий, безусловно, плохая идея, так как это приведет к некачественному коду, версии, которые ваши классы могут работать, если вы просто храните события или другие подобные данные, но на самом деле не подходят для большинства сценариев, так что у вас остается середина вариант.
Я бы порекомендовал сделать именно это и следовать нескольким простым правилам в том же духе, что и вы, имея дело с предварительной схемой в реляционной базе данных.
- Используйте систему VCS для определения изменений между развернутыми версиями
- Напишите сценарии миграции, которые обновляются с одной версии на другую
- Будьте осторожны с переименом/удалением свойств - как загрузка документа и сохранение документа приведет к потерянным данным, если эти свойства не существуют в новом документе
И т.п.
Надеюсь, это более полезно :-)
Другие советы
Ravendb сериализует ваши объекты .NET в формате JSON. Там нет схемы.
Если вы добавите некоторые объекты в свою базу данных, они будут сериализованы. Если вы добавите некоторые свойства к типу, который вы сериализуете, объекты, которые вы уже сохранили, будут пропустить эти свойства.
В этой статье Ayende описывается, как выполнить миграцию с 1 в версию 2 (в этом случае изменение свойства «имя» на свойства «FirstName» и «Lastname».
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");
}
}
У вас нет столько управления схемами, сколько перемещать его в свой код, так что между объектами в вашем коде и в вашей базе данных никогда не существует несоответствия.
Первая часть обработки изменений состоит в том, чтобы убедиться, что вы используете сериализатор, который может обрабатывать отсутствующие/дополнительные значения - если поле не определен в данных, установите его на NULL. Если поле в данных не соответствует свойству на вашем объекте, игнорируйте его.
Большинство изменений могут быть обработаны без чего -либо большего - либо есть новое поле, и вам в любом случае необходимо иметь значение по умолчанию для существующих записей, либо есть старое поле, которое вам больше не волнует.
Для более сложных изменений, таких как поля переименования/объединения или изменение формата данных, добавьте новое поле в свой объект без удаления старых и получите данные о передаче метода нагрузки из старых полей. Когда вы сохраняете запись, он будет в новом формате. Этот код может быть оставлен на месте навсегда, обновляя данные по мере необходимости, либо вы можете настроить однократный процесс, чтобы вызвать один и тот же код для всех существующих объектов. Обратите внимание, что в отличие от сценария SQL, для этого типа обновления не требуется времени простоя, даже если для работы на большом наборе данных требуется много времени, поскольку код может обрабатывать как старые, так и новые форматы.