Генерация LINQ to SQL кода для SQLite в .NET (C#)

от автора

На C# я пишу редко, и в основном все наши приложения и сервисы подключаются к источнику данных, используя MSSQL сервер или службы баз данных. И вот настало время написать приложение, используя не сервер, а локальную БД. Немного погуглив, я внезапно выбрал SQLite.

Предисловие

У всех наших заказчиков были требования к коду:

  • установленное именование переменных;
  • группировка кода (конструкторы, переменные, методы, события…);
  • табы и форматирование (каралось смертной казнью);
  • за самописные SQL запросы разработчик удалялся из команды.

Исходя из вышеперечисленного, для баз данных конечно же были использованы классы LINQ to SQL, связанные с реляционными объектами.

Естественно, в моем десктопном приложении я сразу же скачал и установил SQLite провайдер, создал базу данных, все таблички, связи, создал класс LINQ to SQL, перетянул в него все объекты с обозревателя, и…

приехали

Что делать? Куда бежать?

Конечно же в гугл, с которого плавно перебегаем в stackoverflow! Там у нас over9000 вариантов:

  • да давайте все писать с начала (SQLiteConnection, SQLiteCommand, SQLiteDataReader, SQLiteDataRecord и т.д.):
  • давайте писать запросы вручную;
  • давайте при изменении или добавлении одного поля в таблицу перелопатим весь проект;
  • связи между таблицами для слабаков, будем использовать DataTable и работать с ним по индексам столбцов…

Нет, нет, и еще раз нет. С данными должен работать класс, который отвечает за подключение к БД, выборку, вставку, обновление и удаление записей (DataContext), а разработчик должен использовать объекты, именованные так же, как и реляционные объекты и их свойства!

Решение

Больше ничего не осталось, как искать «левые» генераторы кода для таблицы. Немного погуглив и взвесив все «за» и «против», я остановился на dblinq2007.

Как оказалось позже, он может генерировать не просто файл с исходным кодом, а студийный LINQ to SQL файл со схемой нашей БД и связями! Это как раз то, что и нужно было, и я приступил к разработке. Первый exception: dblinq2007 написан и генерирует схему для Framework 2.0, а мы используем 4.0. Качаем исходники, открываем в студии, в свойствах проектов выбираем 4ю версию фреймворка и пересобираем dblinq2007!

Генерация кода

Для генерации необходимо использовать исполняемый файл dblinq2007, который лежит в директории скомпилированных бинарников и называется DbMetal.exe. Немного покурим его доки, и, просмотрев справку, мы видим, что достаточно указать провайдера, строку подключения и имя файла, и DbMetal сгенерирует нам DBML файл для SQLite:

Генерируем DBML-модель:

После генерации DBML нам необходимо сгенерировать CS файл (должен называться так же, как и DBML файл), в котором и будет описана структура нашей БД со всеми связями. Основной сгенерируемый класс Main унаследован от класса DataContext, в котором и реализована работа с SQLite.

Теперь, когда все файлы сгенерированы, копируем их в директорию нашего проекта и добавляем в проект DBML файл. Чтобы увидеть, что студия теперь работает с SQLite, достаточно в Обозревателе серверов выделить все таблички, и перетянуть их в DBML конструктор:

Победа!

В принципе, все. После проделанных манипуляций мы сможем писать LINQ запросы к нашей БД и нам будут возвращаться объекты со всеми связями.

public class Test {         private void Example()         {             //берем из конфига строку подключения и подключаемся к БД             SQLiteConnection Connection = new SQLiteConnection(Properties.Settings.Default.connectionString);             Connection.Open();              //тот самый DatabaseContext, через который мы работаем с БД             Main dbContext = new Main(Connection, new SqliteVendor());                          //получаем данные             List<Order> OrderList = (from o in dbContext.Order                             select o).ToList();             //или так             List<Order> OrderList = dbContext.Order.Take(10).ToList();              //получаем статус заказа из связанной таблицы             string OrderStatus = OrderList[0].OrderStatus.Name;              //получаем все позиции заказа             List<OrderUnit> OrderUnits = OrderList[0].OrderUnit.ToList();              //получаем изображения позиции             List<MenuImages> UnitImages = OrderList[0].OrderUnit[0].Menu.MenuImages.ToList();              //вставляем данные             Order ord = new Order()             {                 OrderNumber = 1,                 ToTime = DateTime.Now             };             dbContext.Order.InsertOnSubmit(ord);             dbContext.SubmitChanges();                          //Удаляем данные             dbContext.Order.DeleteOnSubmit(OrderList[0]);             dbContext.SubmitChanges();              //закрываем подключение             Connection.Close();         } } 

ссылка на оригинал статьи http://habrahabr.ru/post/262279/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *