Как стать автором
Обновить

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

Время на прочтение3 мин
Количество просмотров17K
На 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();
        }
}
Теги:
Хабы:
Всего голосов 6: ↑4 и ↓2+2
Комментарии8

Публикации

Работа

Ближайшие события