BLToolkit. Intro — I

Уже достаточно давно меня интересует тема CQRS, но пока что все останавливалось на изучении документов, примеров и самому написать что-то используя подход CQRS не доводилось. В последние дни работа в этом направлении активизировалась с новой силой, и пошлел процесс по исследованию инструментов более всего пригодных для реализации этой концепции. Наверно так повлияла конференция Patterns’n’Practices, когда было объявлено что к концу года команда выпустит гайдлайны по реализации CQRS на практике.

Одной из ключевых вещей является непосредственное получение информации из базы данных без промежуточных программных слоев. Такое получение данных должно быть быстрое и простое. Простое и быстрое. По многочисленным источникам и по результатам сайта ORM Battle был выбран для экспериментов BLToolkit.

Насчет скорости работы есть диаграмма сравнения с другими фреймворками на 30 июля 2011 года:

Не могу не вспомнить фразу с презентации на NDC2011 по поводу Kill your ORM, где ведущий высказался в таком духе: «Linq2Sql вышел слишком простым и быстрым, поэтому придумали EF. Больше абстракций!».

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

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

Возможности BLToolkit

Сами разработчики относят свое детище к легковесным ORM, т.е. таким которые управляют только получением/сохранением данных, но не поддерживают связи между сущностями базы данных. По умолчанию не поддерживает. Хотя можно указать маппинг на загрузку, но тогда классы становятся несколько перегруженными аннотациями. Впрочем, в разрезе CQRS меня не очень интересуют возможности подгрузки связанных данных.

Связывание данных делается «по соглашениям», и реже «по контракту» то, что называется convention over contract, хотя возможность указать явно таблицу или процедуру существует. Так же есть возможность задать правило, по которому будут конструироваться имена процедур.

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

Подготовка к работе

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

Для создания нам понадобится любая редакция VisualStudio 2010, а так же SQL Server не ниже 2005. По умолчанию в поставку BLToolkit как минимум входят драйвера для MS SQL 2005, 2008, Microsoft Access. Впрочем, все чудесно работает и с MS SQL Denali

Скрипт для базы

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

Добавление BLToolkit

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

При создании по умолчанию проект будет создан для 4го клиентского профиля, что нам не подойдет совсем. Если не поменять фреймворк с “.Net Framework 4 Client Profile”, на “.Net Framework 4”, то во время компиляции получим такие сообщения:

После того, как сменили версию фреймворка, добавляем BLToolkit с помощью NuGet. Открываем консоль Package Manager Console (Tools > Package Manager Console ) и вводим там:

В результате должен появиться текст:

После добавления ссылки на BLToolkit собираем приложение и убеждаемся, что все компилируется.

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

Это было не сложно, далее начнется основная магия.

DataAccessor

Основным классом для работы с BLToolkit у нас будет DataAccessor. Это абстрактный класс и от него будем наследоваться для написания своего фасада доступа к данным. Данный класс управляет практически всеми аспектами и нюансами работы с базой данных, в нем определенно множество методов, которые можно переопределить для тонкой настройки работы с базой.

Начнем с создания класса, который будет наследован от DataAccessor и так же будет абстрактным.

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

Следующим шагом будет создание метода для получения данных из базы. Он так же будет абстрактным.

Придумываем более-менее адекватное название методу, указываем какой тип данных будет возвращать метод. Естественно, что BLToolkit волшебным образом в данный момент не узнает откуда брать данные. Самый простой способ указать это – воспользоваться атрибутом SqlQuery и написать запрос.

Но и это еще не все, осталось сделать главное, сказать как соединятся с сервером, откуда будем брать данные. Это можно сделать как в файле конфигурации, так и в коде.

Конфигурация соединения с базой в конфигурации приложения (app.config):

Честно сказать я не люблю указывать в конфигурации настройки, поэтому быстро нашел способ как указать это в программе. Как я уже сказал, класс DataAccessor, позволяет тонко настроить многие параметры работы с базой. Можно задать и соединение с базой.

Остается теперь только получить экземпляр класса PersonAccessor в рабочем коде. Это делается несколько необычным способом, в состав BLToolkit входит класс для создания экземпляров классов типа нашего PersonAccessor:

С помощью данного способа вы получаете экземпляр класса PersonAccessor, но он уже не абстрактный. Я так думаю, что во время компиляций исходный абстрактный класс переименовывается и с помощью TypeAccessor на его основе строится новый класс в run-time режиме.

Все,  после этого можно обращаться к методам нашего класса и работать с результатами. Итого:

Результат:

Далее можно экспериментировать с классом Person, добавлять новые поля, удалять, делать их свойствами и все равно класс будет заполняться данными из базы. Порядок полей в классе, естественно, значения не имеет. Советую попробовать поэкспериментировать в этом ключе. И да, заполняютя только публичные поля класса. Если Name будет приватным полем или же иметь приватный set, то значение не будет восстановлено из базы.

Сопоставление данных

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

В нашем случае можно написать представление на таблицу Person:

Модифицировать запрос:

Всё будет работать точно так же как прежде.

Параметры

При использовании атрибута SqlQuery можно передавать в запрос параметры. Что может быть весьма полезно в некоторых случаях.

Для построения запроса с параметрами можно использовать стандартный синтаксис MS SQL, причем имя параметра в запросе должно совпадать с именем параметра в методе.

Далее будет про хранимые процедуры и LINQ

Hard’n’heavy

 

Оставить комментарий