- Регистрация
- 09.10.2015
- Сообщения
- 3 916
- Благодарностей
- 3 866
- Баллы
- 113
Небольшая библиотека для упрощения работы с SQLite базой данных в ZennoPoster.
В первую очередь, данная библиотека поможет исключить множество повторяющегося кода (перехват ошибок, создание SQLiteCommand на каждый запрос, правильную передачу параметров через SQLiteCommand.Parameters). А также, облегчит разработку и упростит обновление и изменение ваших проектов по ходу их развития.
Идея и часть реализации подсмотрена у @DmitryAk + PHP PDO database framework Medoo.
Текущий релиз не избавляет полностью от работы с System.Data.SQLite объектами + содержит несколько изъянов, которые могут допустить SQL-injection (или скорее порчу данных), но даже эта версия уже пригодна для использования (аккуратного).
Установка
Советы по использованию
Описание методов FastSqliteHelper
С полным описанием методов (их параметрами и возвращаемыми значениями) вы можете ознакомиться на странице в github-репозитории.
TODO
Ниже описан план развития, задачи из которого по моему мнению нужно сделать в первую очередь, минуя добавление другого функционала, который может быть реализован непосредственно через работу с System.Data.SQLite.
Если у вас есть непреодолимое желание помочь этому проекту в развитии - посмотрите ниже, что я хотел бы видеть в следующих версиях этой библиотеки, сделайте Fork репозитория и отправьте свой Pull Request с решением любой из задач
Послесловие
В прикрепленных ниже файлах вы найдете архив со скомпилированными библиотеками и тестовый шаблон с примерами работы практически всех методов. Вся дополнительная документация и весь исходный код опубликованы в github-репозитории: https://github.com/lord-alfred/FastSqliteHelper
На самом деле, изначально я отправлял заявку на конкурс для совсем другого шаблона, но в ходе его написания появилась острая необходимость в таком легковесном SQLite C# wrapper, чтобы было удобнее манипулировать данными. Но это уже совсем другая история...)
В первую очередь, данная библиотека поможет исключить множество повторяющегося кода (перехват ошибок, создание SQLiteCommand на каждый запрос, правильную передачу параметров через SQLiteCommand.Parameters). А также, облегчит разработку и упростит обновление и изменение ваших проектов по ходу их развития.
Идея и часть реализации подсмотрена у @DmitryAk + PHP PDO database framework Medoo.
Текущий релиз не избавляет полностью от работы с System.Data.SQLite объектами + содержит несколько изъянов, которые могут допустить SQL-injection (или скорее порчу данных), но даже эта версия уже пригодна для использования (аккуратного).
Установка
- Скомпилировать самостоятельно или взять последнюю версию FastSqliteHelper.dll из релизов и положить в директорию:
Код:C:\Program Files (x86)\ZennoLab\RU\ZennoPoster Pro\[версия ZP]\Progs\ExternalAssemblies
- Скопировать System.Data.SQLite.dll и SQLite.Interop.dll из папки sqlite-netFx46-binary-x64-2015-1.0.107.0 (или скачать из последнего релиза) в вышеприведенную директорию ExternalAssemblies
- В проекте выбрать Добавить действие -> Свой код -> Ссылки из GAC
- Зайти в появившийся внизу блок References (в Расширенном редакторе), нажать кнопку Добавить..., затем кнопку Обзор...
- В появившемся окне выбрать:
Код:C:\Program Files (x86)\ZennoLab\RU\ZennoPoster Pro\[версия ZP]\Progs\ExternalAssemblies\FastSqliteHelper.dll
- Повторить пункт 4 и в появившемся окне выбрать:
Код:C:\Program Files (x86)\ZennoLab\RU\ZennoPoster Pro\[версия ZP]\Progs\ExternalAssemblies\System.Data.SQLite.dll
- В проекте выбрать Добавить действие -> Свой код -> Директивы using и общий код
- Зайти в появившийся внизу блок OwnCodeUsings (в Расширенном редакторе) и в окне "Директивы Using" вставить:
C#:using FastSqliteHelperLib; using System.Data.SQLite;
Советы по использованию
- Примеры работы практически со всеми методами есть в шаблоне test_project.xmlz
- При использовании многопоточных шаблонов в ZennoPoster всегда добавляйте к строке дополнительных параметров connection string в методе FastSqliteHelper.Init включение типа журнала WAL с помощью:
Код:Version=3;Journal Mode=WAL;
- Всегда закрывайте соединение с базой данных через метод FastSqliteHelper.DeInit.
- Если в результате выполнения какого-либо из методов в результате возвращается объект класса System.Data.SQLite.SQLiteDataReader ("читатель"), то необходимо всегда закрывать его через метод .Close, чтобы избежать ошибок в многопотоке.
Пример корректного закрытия "читателя" при получения множества строк с помощью метода FastSqliteHelper.Select:
C#:System.Data.SQLite.SQLiteDataReader reader = FastSqliteHelper.Select("table_name", new string[]{"id", "value"}); try { foreach(dynamic row in reader) { project.SendInfoToLog("Строка: " + row["id"] + " -> " + row["value"]); } } finally { reader.Close(); }
C#:System.Data.SQLite.SQLiteDataReader reader = FastSqliteHelper.Select("table_name", "count(id) as count_all"); int count = 0; try { if (reader.Read()) { count = Convert.ToInt32(reader["count_all"]); } } finally { reader.Close(); }
- Если в каком-то условии (condition) для выборки/обновления/удаления вам нужно сделать LIMIT, ORDER BY или что-то, что идет за WHERE - не забывайте, что в библиотеке это условие конкатенуется ("склеивается") с:
Код:WHERE 1=1 and
Код:2=2 LIMIT 0,10
- Для массового добавления строк в таблицу необходимо открывать транзакцию (пример реализации работы через транзакцию есть в методе FastSqliteHelper.Insert, но он может быть неудобен для ваших задач, т.к. предварительно нужно будет сделать список словарей с данными для вставки). Если не открывать транзакцию, то SQLite сделает это неявно на каждый Insert, поэтому у вас с очень большой долей вероятности будут "тормоза". Также, для ускорения процесса вставки (только при использовании в однопоточном шаблоне!) лучше отключить тип журнала и тип синхронизации при подключении к БД:
Код:Journal Mode=OFF;Synchronous=0;
- В SQLite при дефолтном "journal_mode" очень просто поймать состояние "database is locked", оно возникает в том случае, если первый поток читает данные из таблицы, а второй поток туда пишет. Чтобы предотвратить такого рода поведение - нужно заранее продумывать логику работы шаблона и обязательно использовать оператор блокировки:
C#:lock(YourOwn.LockerObject) { // работа с БД через методы FastSqliteHelper }
- Всегда явно указывайте столбцы для выборки, избегайте "*" для возвращения всех столбцов из таблицы. Это ускорит работу и поможет избежать ошибок, допущенных по невнимательности.
- В методе подключения к БД есть один очень важный параметр: throw_exc_on_errors - "выдавать ли исключение в случае ошибки или просто по-тихому писать в лог ZP". Я настоятельно рекомендую выставлять его всегда в true, чтобы в случае ошибки - шаблон останавливал свое выполнение и прекращал работу, минуя тем самым другие ошибки, которые могут произойти далее.
- К сожалению, в текущей реализации невозможно работать с 2 и более более SQLite базами данных одновременно. Это ограничение связано с тем, что класс FastSqliteHelper и его методы - статические. Можно сделать "хак" с monkey-patching объекта подключения и переопределять его "на лету", но это не тот подход, который хотелось бы предлагать для использования. Возможно, когда-то в дальнейшем эта оплошность будет устранена.
- Для удобного просмотра/изменения базы данных я советую использовать бесплатную программу SQLiteStudio (в ней есть русификация).
- Помните, что SQLite в первую очередь - это встраиваемая база данных в одном файле, поэтому ожидать от неё существенного прироста производительности - не стоит. Для таких целей лучше использовать MySQL или PostgreSQL. Но в целом, для небольших проектов/шаблонов, в которых не будет миллионов строк в базе - это очень хорошее решение, которое поможет избавиться от "списков" и "таблиц" в ZennoPoster.
Советую к прочтению небольшой цикл статей о SQLite на хабре.
Описание методов FastSqliteHelper
- FastSqliteHelper.Init — Инициализация подключения к SQLite базе данных.
- FastSqliteHelper.Init — Инициализация подключения к SQLite базе данных (дополнительные параметры connection string в виде словаря).
- FastSqliteHelper.DeInit — Закрытие подключения к базе данных.
- FastSqliteHelper.PragmaSet — Установка параметра PRAGMA для текущего подключения к БД.
- FastSqliteHelper.PragmaGet — Чтение параметра PRAGMA из текущего подключения к БД.
- FastSqliteHelper.Select — Получение данных из таблицы по условию (столбцы в виде строки).
- FastSqliteHelper.Select — Получение данных из таблицы по условию (столбцы в виде массива строк).
- FastSqliteHelper.Select — Получение данных из таблицы по условию (столбцы в виде списка).
- FastSqliteHelper.Insert — Добавление одной записи в таблицу.
- FastSqliteHelper.Insert — Добавление множества записей в таблицу (используя транзакцию на все добавляемые данные).
- FastSqliteHelper.LastInsertID — Идентификатор последней добавленной записи.
- FastSqliteHelper.Update — Обновление значений в таблице по указанному условию.
- FastSqliteHelper.Update — Обновление значения одного столбца в таблице по указанному условию.
- FastSqliteHelper.Delete — Удаление записей из таблицы по указанному условию в виде строки.
- FastSqliteHelper.Delete — Удаление записей из таблицы по указанному условию в виде словаря.
- FastSqliteHelper.Query — Любой запрос к БД, возвращающий количество затронутых строк.
- FastSqliteHelper.QueryReader — Любой запрос к БД, возвращающий объект SQLiteDataReader с содержимым.
- FastSqliteHelper.QueryScalar — Любой запрос к БД, возвращающий первый столбец первой строки.
- FastSqliteHelper.GetLastQuery — Получить последний отправленный запрос (включая запросы, в ходе обработки которых возникла ошибка).
TODO
Ниже описан план развития, задачи из которого по моему мнению нужно сделать в первую очередь, минуя добавление другого функционала, который может быть реализован непосредственно через работу с System.Data.SQLite.
Если у вас есть непреодолимое желание помочь этому проекту в развитии - посмотрите ниже, что я хотел бы видеть в следующих версиях этой библиотеки, сделайте Fork репозитория и отправьте свой Pull Request с решением любой из задач
- Написать тесты для каждого метода, чтобы в случае выпуска нового релиза можно было проверить не сломалось ли что-то где-то.
- Реализовать тестовый проект для консольного приложения, чтобы не было нужды проверять все методы в ProjectMaker, а была возможность работы в VisualStudio/SharpDevelop.
- Проверить и разобраться почему при установке какого-либо значения PRAGMA через строку подключения - чтение этого параметра через метод PragmaGet получает другой результат.
- Избавиться от возвращения SQLiteDataReader в нескольких методах, чтобы можно было не думать о том, что его нужно всегда "закрывать".
- Облегчить работу с транзакциями (избавиться от явного вызова Commit/Rollback), используя анонимные функции (делегаты в C#?).
Пример правильной организации выполнения запросов внутри транзакции на PHP: https://medoo.in/api/action - Реализовать передачу условий в методы, чтобы они не "склеивались" с условием WHERE 1=1 and, чтобы была возможность передать LIMIT 0,10 без добавления конструкции вида 2=2.
- Продумать и реализовать способ передачи условий в виде "столбец" => "значение" без ограничения на то, что все имена столбцов должны быть уникальны.
- Добавить метод для экранирования значений, которые могут быть в дальнейшем переданы в виде plain-запроса в методы Query*.
Пример похожего функционала в PHP PDO драйвере: http://php.net/manual/ru/pdo.quote.php - Добавить возможность работы с несколькими SQLite базами одновременно (убрать статический модификатор для класса, но это повлечет проблемы при передаче объекта через project.Context в ProjectMaker или сделать поле connection в виде словаря подключений, но нужно будет предварительно протестировать этот вариант в многопоточном режиме, чтоб не вышло, что данные будут пересекаться).
- Переименовать методы Init -> Open, DeInit -> Close. Сомнительно и добавит обратную несовместимость, но читаемость кода повысится.
- Реализовать получение/вставку/обновление/удаление данных через объекты, а не через словари. Плюс - не нужно будет делать некрасивые словари для работы с этими методами; минус - для каждой таблицы, с которой нужно будет работать - нужно будет создавать классы и вести работу через них.
- Проверить и исправить все методы, которые подвержены sql-injection, чтобы в ходе работы не испортились данные.
- В методах, которые не требуют работы с параметрами (SQLiteCommand.Parameters) - переписать отправку запроса/получение результата через внутренние методы Query*. Но это может привести к тому, что будет сложно разобрать в сообщении об ошибке - откуда именно упало исключение (поэтому данная задача под сомнением).
- Добавить метод, который будет возвращать последний выполненный запрос (или даже лучше - отправленный, чтобы в случае перехвата ошибки внутри метода его можно было отобразить).
Пример такого функционала в PHP фреймворке Medoo: https://medoo.in/api/last - Подумать над тем, что в последний отправленный запрос может быть списком (логом) всех запросов. Плюс решить стоит ли там заменять параметры на их значения.
- Написать Contributing Guidelines, которые будут включать в себя: правильную настройку редактора, чтобы избежать табуляций в коде; использование String.Format и String.Concat; удаление trailing whitespace и другие полезные вещи.
Послесловие
В прикрепленных ниже файлах вы найдете архив со скомпилированными библиотеками и тестовый шаблон с примерами работы практически всех методов. Вся дополнительная документация и весь исходный код опубликованы в github-репозитории: https://github.com/lord-alfred/FastSqliteHelper
На самом деле, изначально я отправлял заявку на конкурс для совсем другого шаблона, но в ходе его написания появилась острая необходимость в таком легковесном SQLite C# wrapper, чтобы было удобнее манипулировать данными. Но это уже совсем другая история...)
- Категория
- Полезно
- Номер конкурса шаблонов
- Первый конкурс шаблонов
- Уровень сложности
- Продвинутый
Вложения
-
833,4 КБ Просмотры: 923
-
40,5 КБ Просмотры: 925
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование: