
Анонс четвёртой версии redb.Core: ссылки грузятся по обращению, уникальность на любом поле, схема обновляется сама. Бесплатно, три СУБД, Free и Pro одинаково.
Готовится redb.Core 4.0. За год это первый мажор такого масштаба: не смена номера, а качественное расширение функционала. Он про три вещи, которые чаще всего просили: ленивая загрузка ссылок между объектами, уникальные ключи на любом поле и обновление схемы базы без ручных действий администратора. Всё вместе, на трёх СУБД сразу и без разделения на «в Free так, в Pro иначе».
Коротко, что изменится для приложения.
Ссылки грузятся тогда, когда их читают
Объект RedbObject<T> умеет ссылаться на другие объекты через свойства Props: заказ ссылается на клиента, клиент на менеджера, менеджер на отдел. До 4.0 один LoadAsync заказа тянул всю эту цепочку на десять уровней вглубь, а единственный способ ограничить аппетит был параметр depth, который просто обрезал ссылки в никуда.
В 4.0 ссылка на границе глубины стала ленивой: у неё есть id, схема и хеш, а Props подгружаются при первом обращении. Ровно этот объект, ровно один запрос. По смыслу это lazy-loading прокси из Entity Framework, только без динамического подкласса: тот же RedbObject<T>, у которого загружены базовые поля и подвешен загрузчик. Его собственные ссылки при этом тоже ленивые, так что ленивость транзитивна и не зависит от того, с какой глубины вы начали.
var order = await redb.LoadAsync<OrderProps>(id, depth: 1); var customer = order.Props.Customer; // ленивая ссылка: id, scheme_id, hash var city = customer.Props.City; // первое обращение загрузило клиента, и только его
Кому нужен явный контроль, тот помечает ссылку virtual (та же конвенция, что у навигационных свойств EF) и включает EnableLazyReferences: такие ссылки остаются ленивыми на любой глубине, а WithLazyReferences(false) на конкретном запросе возвращает жадную загрузку. Коллекция ленивых ссылок дозагружается одним запросом через LoadReferencesAsync.
Сохранение родителя, вычисление хеша и сериализация в JSON ленивые ссылки не будят. Проверка этих трёх утверждений есть в тестах на каждой из шести конфигураций.
Уникальность на любом поле
Два механизма, для двух разных задач.
ValueUnique у объекта: читаемый строковый ключ (номер заказа, артикул, внешний идентификатор), уникальный в рамках схемы, с поиском по LINQ и SaveByUniqueAsync как upsert по ключу.
[RedbUnique] на поле Props: уникальность значения любого скалярного типа, включая decimal, даты и byte[], обеспеченная индексом базы. Нарушение на всех трёх СУБД поднимается одним типизированным RedbUniqueViolationException, а не тремя разными ошибками драйвера.
public class ProductProps { [RedbUnique] public string Sku { get; set; } = ""; [RedbUnique] public byte[]? Fingerprint { get; set; } } var product = await redb.GetByUniqueAsync<ProductProps>(p => p.Sku, "SKU-1001");
База обновляется сама, а если не может, говорит об этом
4.0 ставится поверх любой базы 3.x. Схема только дополняется: новые колонки с NULL, частичные индексы, новые функции. Ничего не удаляется и не переименовывается, откат на 3.x остаётся возможным.
Обновление применяется при старте приложения. Если у роли приложения нет прав менять схему, старт останавливается типизированным RedbSchemaOutdatedException с указанием версий, а сам скрипт обновления отдаёт GetUpgradeScript() и команда redb schema --upgrade: DBA применяет его сам. Есть и режим AutoApplyDatabaseUpgrades = false для тех, кто хочет держать схему под ручным контролем всегда.
Мелочи, которые заметите
byte[]хранится одним BLOB, а не строкой на байт. Старая раскладка конвертируется на первой синхронизации схемы.Схема знает, из какого namespace её тип. Два разных
Orderиз двух проектов больше не могут молча усыновить схему друг друга.В SQLite хеши стали
BLOB(16), файлы старого формата конвертируются при открытии.
Что сломается
Убран старый механизм ленивой загрузки Props целиком: EnableLazyLoadingForProps, WithLazyLoading() и параметр lazyLoadProps у LoadAsync. Он делал ленивым дешёвое и жадным дорогое, жил за тремя переключателями и не имел тестов. По умолчанию он был выключен, так что проект без этих настроек ничего не заметит; в остальных достаточно удалить флаг и вызов.
Цифры и условия
Три СУБД (PostgreSQL, MSSQL, SQLite), два издания, шесть тестовых конфигураций, 2304 интеграционных теста зелёные на финальной сборке. Каждая новая проверка доказана красной на непочиненном коде.
Четвёртая версия остаётся бесплатной: Pro-возможности не требуют лицензионного ключа во всей линии 4.x, как и в 3.x. Пакеты redb, redb.Route, redb.Tsak и redb.Identity выходят одним номером.
Полный разбор с примерами на каждую возможность выйдет вместе с релизом: redb.ru/articles.
Если было полезно, ⭐ на GitHub поможет другим это найти.
Другие мои статьи — redb.ru/articles, ещё — на Хабре.

