Коллекции Mongo Schema-less и С#

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

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

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

Edit: Стоит отметить, что эти проблемы, очевидно, существуют и в реляционных базах данных, но я задаю конкретно стратегии по смягчению проблемы с использованием баз данных schemaless и, более конкретно, Mongo. Спасибо!

Ответы

Ответ 1

Миграция схемы с MongoDB на самом деле намного менее болезненна, чем, скажем, SQL-сервер.

Добавление нового поля легко, старые записи войдут с ним в значение null или вы можете использовать атрибуты для управления значением по умолчанию [BsonDefaultValue("abc", SerializeDefaultValue = false)]

Атрибут [BsonIgnoreIfNull] также удобен для удаления объектов, которые являются нулевыми из документа при его сериализации.

Удаление поля довольно просто, вы можете использовать [BSonExtraElements] (см. docs), чтобы собрать их и сохранить их, или вы можете использовать [BsonIgnoreExtraElements] просто выбросить их.

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


PS, так как вы также заинтересованы в использовании динамического с Mongo, здесь эксперимент, я пробовал эти строки. И здесь обновленный пост с полным сериализатором и десериализатором для динамических объектов.

Ответ 2

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

У моих репозиториев будет минимальная требуемая версия, которую они требуют для точной сериализации и десериализации элементов коллекций. Если текущая версия db ниже требуемой версии, я просто бросаю исключение. Затем используйте миграции, которые сделают все необходимые преобразования для обновления коллекций до требуемого состояния для десериализации и обновления номера версии базы данных.

Ответ 3

При использовании статически типизированных языков, таких как С#, всякий раз, когда объект сериализуется где-то, тогда его первоначальный класс изменяется, а затем десериализуется обратно в новый класс, вы, вероятно, будете сталкиваться с проблемами где-то вдоль линии. Это довольно неизбежно, будь то MongoDB, WCF, XmlSerializer или что-то еще.

У вас обычно есть гибкость с параметрами сериализации, например, с Mongo вы можете изменить имя свойства класса, но все еще иметь свою карту значений к тому же имени поля (например, с использованием атрибута BsonElement). Или вы можете указать десериализатору игнорировать поля Mongo, которые не имеют соответствующего свойства класса, используя атрибут BsonIgnoreExtraElements, поэтому удаление свойства не вызовет исключения, когда старое поле загрузится из Mongo.

В целом, хотя для любых изменений структурной схемы вам, вероятно, потребуется перезагрузить данные или выполнить миграцию script. Другой альтернативой является использование динамических переменных С#, хотя на самом деле это не решает основную проблему, вы получите меньше ошибок сериализации.

Ответ 4

Я использую mongodb чуть больше года, но не для очень больших проектов. Я использую hugo csmongo или fork здесь. Мне нравится динамический подход, который он вводит. Это особенно полезно для проектов, в которых структура базы данных нестабильна.