Несколько лет назад я использовал RavenDB, и это был хороший опыт — с тех пор он только рос как на дрожжах. Раньше я много использовал MongoDB, мне надоел «опыт SQL», и мне нужно было что-то получше для ООП. Но теперь я FP и DDD, SQL не поможет, а Mongo раздражает меня.
Начало работы с RavenDB
Перво-наперво, нам нужна локальная среда
docker run --rm -d -p 9010:8080 -p 38888:38888 --name ravendb -e RAVEN_Setup_Mode=None -e RAVEN_License_Eula_Accepted=true -e RAVEN_Security_UnsecuredAccessAllowed=PrivateNetwork ravendb/ravendb
Там есть несколько переменных среды, и они необходимы. RAVEN_Setup_Mode=None
Это выбирает безопасность во время установки, по сути, просит RavenDB запуститься без процесса настройки — удалите, и вам придется проходить через мастер настройки каждый раз, когда вы создаете контейнер, болезненно для автоматизации. "Больше информации…"
RAVEN_License_Eula_Accepted=true
Опять же, еще один процесс настройки. RAVEN_Security_UnsecuredAccessAllowed=PrivateNetwork
Это связано с тем, что по умолчанию включена проверка подлинности TLS и сертификата, что делает сервер доступным без проверки подлинности. "Больше информации…"
Подключение к RavenDB
Есть пример C#, который я придумал:
Я использую классы и интерфейсы, потому что DI по-прежнему прост, и я перехожу к F# — не нужно возиться с монадами и влезать в ад множественных монад.
.AddSingleton<IRavenClientFactory, RavenClientFactory>(fun sp -> let configurationSection = config.GetSection("Raven") let url = configurationSection.GetValue("Url") let dbName = configurationSection.GetValue("Database") new RavenClientFactory([ url ], dbName) )
Чтение из RavenDB
Я создал простую оболочку для чтения и записи. Не более чем просто справиться с дополнительными ортогональными проблемами, которые появятся позже.
Не беспокойтесь о ErrorResponse<'t>
, это просто размеченный союз, который позволяет мне превращать исключения и другие события в полезную информацию для понимания на границе API. Таким образом, если это временная ошибка, я могу вернуть 500 и попросить клиента повторить попытку или что-то в этом роде…
В этом нет ничего сверхъестественного, просто довольно стандартные вещи.
Интересное время
Итак, давайте углубимся в некоторые более интересные аспекты.
- Я хочу автоматическое создание базы данных
- Бесшовная интеграция с объектами домена и объектами значений
Автоматическое создание базы данных
Почему? Во время локальной разработки я переключаюсь между компьютерами, иногда я использую свой «большой» компьютер — он же Tower PC — иногда мне нравится сидеть и смотреть телевизор во время кодирования — как я делаю сейчас, пока пишу этот блог. Каждый раз я хочу, чтобы моя база данных и другие ресурсы моих API/веб-сайтов могли автоматически генерировать исходные данные и т. д.
Оказывается, в RavenDB создание новой базы данных немного громоздко. В отличие от SQL или Mongo, где простой запуск запроса либо создаст базу данных, либо автоматически сгенерирует коллекцию, RavenDB требует взаимодействия с Maintenance
API. По этой ссылке вы увидите пример C#, давайте сделаем его забавным.
Здесь вы увидите Retries
, небольшую обертку вокруг Полли, которую я написал.
Это начинается с checkForDatabase
, который возвращает Result<unit, unit>
, по сути, если он возвращает Error ()
, нам нужно создать базу данных.
Затем мы createIfNotExists -> tryCreateDatabase
. tryCreateDatabase
пожары CreateDatabaseOperation
. Если это вызывает исключение ConcurrencyException
, мы можем его игнорировать, потому что оно уже создается где-то еще. Если исключение RavenException
, то, вероятно, это связано с тем, что сервер еще не готов, и его просто нужно повторить, пока он не завершится успешно. Он никогда не терпел неудачу в 20 повторных попытках, так что это кажется разумным.
env
— это IWebHostEnvironment
, чтобы я мог проверить, находимся ли мы в режиме разработки. Сделано так себе ravenClientFactory.InitialiseDatabase env
.
Так вот, в значительной степени dunzo'd ...
Полная интеграция с DDD
Что ж, придется подождать до следующего раза... :D