WildData: легкий фреймворк доступа к данным

в 22:18, , рубрики: .net, C# data linq, метки:

Доброго времени суток, %username%! Вот и я решился на написание статьи на данном ресурсе. Речь пойдет о доступе к данным из приложений написанных на .NET, в частности на языке C#. Все мои мысли, и во что они в итоге вылились, я попытаюсь изложить под катом. Добро пожаловать!

Под СУБД в статье будем понимать реляционную СУБД. Забегая вперед, скажу, что представленная библиотека (фреймворк) не является заменой Entity Framework, не зависит от него и не имеет к нему никакого отношения.

Тем не менее, оттолкнёмся от вышеупомянутого фреймворка. Одна из его идей – попытка (и весьма удачная) введения абстракции доступа к данным. Иными словами уход от конкретной СУБД.

Каждая СУБД имеет свои плюсы и свои минусы: некоторые имеет одни возможности, некоторые другие; некоторые делают хорошо одно, другие – другое и т.д. Давайте теперь представим, что взвесив все «за» и «против» мы выбрали некую СУБД для реализации какого-то грандиозного (или не очень) проекта и решили писать всё это с использованием… ADO.NET.

Плюсы ADO.NET:

  1. полный контроль над запросами;
  2. относительная простота: создать подключение, создать транзакцию (опционально), создать команду, добавить текст запроса и параметры, запустить, считать данные (опционально);
  3. есть поддержка практически для любой СУБД.
  4. тесное взаимодействие с СУБД (например, поддержка таких «нестандартных» типов данных как координаты, JSON и т.д.).

Минусы ADO.NET (предпосылки к реализации проекта):

  1. для каждой модели необходимо каждый раз заново писать код для чтения, добавления и изменения записи в БД – проще говоря отображения объекта на запись в таблице, представлении т.д. и, наоборот, отображение записи на объект;
  2. Нет абстрагирования как в Java (хотя есть DbConnection/DbCommand и другие классы, но часто используются конкретные типы, например SqlConnection/SqlCommand);
  3. Нет универсальной поддержки работы с пакетом записей (добавление, обновление, добавление или обновление, удаление);

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

Начнем по порядку.

  1. Что же мы можем сделать для того, чтобы написать этот код один раз? В первую очередь заметим, что костяк для чтения одного или нескольких объектов остается неизменным вне зависимости от того что это за объект и какие поля он содержит. Это означает, что нам необходима универсальная функция чтения одного объекта. То же верно для добавления и обновления записи.

    Как такая функция должна быть написана? Первое что приходит на ум – Reflection. Допустим. Но у Reflection есть один существенный недостаток – он медленный. Если при чтении/добавлении/изменении/удалении одного объекта быстродействие просядет несущественно, то при большом количестве объектов накладные расходы будут ощутимы.

    На помощь нам придут Expression'ы и возможность их компиляции «на лету». Идея состоит в том, что тело функции генерируется, компилируется и ссылка на нее сохраняется в виде делегата. Делать это необходимо только один раз – при инициализации.

    С чем должны работать функции? С тремя сущностями:

    • объект как таковой (модель);
    • объект чтения данных (например, SqlDataReader);
    • коллекция параметров (например, SqlParameterCollection).

    Для того, чтобы точка генерация данных функций была едина, введены следующие интерфейсы обёрток: IDbParameterCollectionWrapper и IReaderWrapper (см. ссылку на репозиторий проекта ниже). Для каждой СУБД необходимо реализовывать эти интерфейсы индивидуально. Забегая вперед: фреймфорк нацелен в первую очередь на скорость работы, поэтому в ряде случаев используется отложенная («ленивая») инициализация. Так же фреймфорк содержит несколько вспомогательных атрибутов для бóльшей гибкости (например, вычисляемые поля, обязательные поля и т.д.).

  2. Вся общая часть фреймфорка вынесена в отдельный общий проект. Для пользователя видны в основном интерфейсы. Крайне рекомендуется пользоваться только интерфейсами.
  3. Пакетная работа с записями пока не реализована, но это уже «дело техники».

Проект уже можно опробовать (см. ссылки ниже). Имеется поддержка Linq! Проект в альфа-версии, поэтому код пока неидеален.

Что планируется добавить:

  • больше тестов;
  • поддержка других баз данных: в первую очередь SQL Server, MySQL;
  • поддержка Microsoft.AspNet.Identity.

Ссылки:

» Проект WildData на GitHub.
» Nuget-пакет WildData.
» Nuget-пакет WildData (реализация для PostgreSQL).
» Очень простой пример использования фреймворка.

Строго прошу не судить. Это моя первая статья на хабрахабре. Спасибо за внимание!

P.S. По всем вопросам прошу в личку и комментарии.

Автор: fox_anthony

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js