GrabDuck

SQLite в .NET | ШПАРГАЛКО СУМАСШЕДШЕГО ПРОГРАММЁРА

:

Не так давно, у меня появилась необходимость сохранять довольно большие объёмы данных в софтинке, которую пишу в свободное время. А именно это список пиров, состоящий из нескольких полей: ID|PEER_IP|STATUS. Возникла необходимость их как-то структурировано хранить, обновлять, и вообще — производить те или иные операции над записями. Логичным решением выглядит использование тех или иных БД. Но — по факту для целостной программы подходит только один тип решения — это SQLite . Дело в том, что это библиотека БД, которая может встраиваться в приложение и использоваться прямо из неё, без коннекта к стороннему серверу, наподобие MySQL. Для небольшого объёма данных (< 1000000 записей) это оптимально. Во-первых, вам достаточно просто включить библиотеку (*.dll) в комплект поставки, и не надо устанавливать на клиентском компьютере какие-то посторонние приложения, вроде MySQL сервера, которые (хотя на современных машинах это и неважно) потребляют некоторое количество ресурсов, как память, например. А зачастую нам нужно получить некоторый набор данных только при загрузке приложения — и постоянно держать ради этого включённым сервер БД — не нужно, плюс переносимость хромает. Встраиваемое решение в виде SQLite позволяет преодолеть эти трудности (и заиметь некоторые другие). Но — по порядку.

Что нужно для того, чтобы использовать SQLite в программах на C#? Для начала, нужно скачать провайдер ADO .NET для работы с SQLite в C#, да и в любом языке платформы .NET. Скачать его можно здесь . Там справа ссылочка «Downloads», которая перебросит на sourceforge. Качаем, устанавливаем. В комплекте идут библиотеки как для x86, так и для x64 платформ, а также для Compact .NET Framework, и экзотики вроде Itanium. Ещё есть полезная приблуда для Visual Studio — позволяет конструировать таблицы прямо из среды разработки. Также, для полноценной работы SQLite в .NET после того, как вы установили провайдер, требуется во-первых, указать в менеджере проектов использование библиотеки System.Data.SQLite, а во-вторых, подключить к файлу пространства имён:

using System.Data;
using System.Data.Common;
using System.Data.SQLite;

Всё, теперь вам доступны для манипуляций объекты  типа SQLiteConnection, SQLiteFactory, SQLiteCommand, SQLiteDataReader. По большому счёту, с ними можно сделать все основные операции, которые встречаются на базах данных. В качестве примера приведу свой вариант класса, для работы с базой SQLite:

Spoiler Inside Select Show

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
using System.IO;
using System.Windows.Forms;

namespace SQLite
{

///
/// Драйвер встраиваемой БД SQLite. Обеспечивает выполнение запросов и разбор возвращаемых
/// этими запросами данных.
///
/// Разработчик: Alex.
/// Дата создания: 07.06.2010
/// Website: http://www.shpargalko.com/
/// Email: allexx.under@gmail.com
///
class CSQLiteDriver
{
private string dbFileName;
private SQLiteFactory sqlFactory;
private SQLiteConnection connection;

public CSQLiteDriver(string dbFileName)
{
try
{
this.dbFileName = dbFileName;
if (!File.Exists(this.dbFileName))
{
SQLiteConnection.CreateFile(this.dbFileName);
}
this.sqlFactory = (SQLiteFactory)DbProviderFactories.GetFactory(«System.Data.SQLite»);
this.connection = (SQLiteConnection)this.sqlFactory.CreateConnection();
this.connection.ConnectionString = «Data Source = » + dbFileName;
this.connection.Open();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}

public int NonExecuteQuery(string query)
{
try
{
SQLiteCommand command = new SQLiteCommand(this.connection);
command.CommandText = query;
command.CommandType = CommandType.Text;
return command.ExecuteNonQuery();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return 0;
}
}

public SQLiteDataReader Query(string query)
{
SQLiteCommand command = new SQLiteCommand(this.connection);
command.CommandText = query;
command.CommandType = CommandType.Text;
SQLiteDataReader reader = command.ExecuteReader();
return reader;
}

public void Close()
{
try
{
this.connection.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
}

}

Вы можете использовать его свободно, при сохранении комментария вверху. Если не хотите — можете просто задействовать из него идеи и написать нечто лучшее :) Отдельного разговора требуют пара методов, которые обозначены здесь как public int NonExecuteQuery(string query) и public SQLiteDataReader Query(string query). Первый — используется для запросов на БД типа INSERT/UPDATE/CREATE — одним словом таких, которые не подразумевают возврата результатов запроса. Хотя кое-что он возвращает — это число строк задетых запросами типа UPDATE/INSERT. Второй — как раз таки предназначен для исполнения запросов с возвратом результата. Результирующий объект — SQLiteDataReader— требует отдельного рассмотрения.

Простейший код для получения результатов смотрите ниже:

Spoiler Inside Select Show

CSQLiteDriver driver = new CSQLiteDriver(«Data/base.sqlite»);
SQLiteDataReader reader = driver.Query(«SELECT * FROM `peers`; «);
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine(«id: {0}; ip: {1}; status: {2};», reader.GetValue(0), reader.GetValue(1), reader.GetValue(2));
}
}

Здесь мы выводим все данные из таблицы в консоль. В нашем случае это три поля таблицы peers. УЖЕ СОЗДАННОЙ и НАПОЛНЕННОЙ данным в базе base.sqlite. Обратите внимание — здесь нет ассоциативных индексов столбцов как в PHP. Обращение происходит по числовому индексу, и отсчёт начинается с нуля.

Дополнительно я рекомендую вам прочитать вот эту страничку: http://www.sqlite.org/lang.html — если вы знаете английский язык. И http://sb-money.ru/sqlite.php?page=21 — если вы не знаете английский, и хотите документацию на русском. Эти две ссылки представляют собой описание диалекта SQL запросов в SQLite.

Да, и ещё очень важный момент — SQLite в .NET начинает глючить при работе программы на сменном носителе с работой на запросах INSERT/UPDATE — например флешке, она выдаёт исключение типа «Some kind of disk I/O error occurred disk I/O errorSQLite. at System.Data.SQLite» Полазив по оф. форуму, а также иным англоязычным ресурсам решения я нигде не нашёл, только доводы почему это происходит. Если вы вдруг найдёте решение этой проблемы, то пожалуйста, потратьте минутку и отпишите в камент к этой заметке.

http://sqlite.phxsoftware.com/