• Программинг

Нужны источники бесперебойного питания?

Источники бесперебойного питания от дизельстор

Примеры использования dbFacad. (SELECT)

В цикле прошлых статей я рассказал, как работать с классом dbFacade. Сегодня же, мы рассмотрим реальные примеры. Как это все работает – не спрашивайте, а читайте предыдущие посты по данной теме.

Давайте предположим, что у нас есть две таблицы со следующей структурой:

Таблица Song
id INTEGER //код песни
name TEXT //название песни
cd_id INTEGER //код диска, к которому относится песня

Таблица CD
id INTEGER //код диска
title TEXT //название диска
publish DATETIME //дата публикации

И так, у нас есть компакт-диски (таблица CD) и список песен (таблица Song). Песни связываются с таблицей CD через поле cd_id, в котором указывается значение поля CD.id. Один диск может содержать несколько песен. Давайте построим запрос для выборки. Предположим, что у нас уже заполнены обе таблицы.

В этом и последующих примерах предполагается, что объект с именем db, уже инициализирован:

1 dbFacade db = new dbFacade();

Самый простой запрос:

1 //SELECT * FROM CD
2 DataTable dt = db.FetchAll("CD"); //вернет все записи со всеми существующими полями

Чуть сложнее:

1 //SELECT * FROM CD WHERE title LIKE '%jovy%'
2 DataTable dt = db.FetchAll("CD","title LIKE '%jovy%'"); //все записи, в поле title которых присутствует jovy

На самом деле метод FetchAll используется редко. Если у вас много полей, а получить необходимо лишь пару, то лучше использовать метод FetchByColumn:

1 //SELECT publish FROM CD WHERE title LIKE '%jovy%'
2 DataTable dt = db.FetchByColumn("CD", "publish", "title LIKE '%jovy%'"); //тоже самое, что и в предыдущем примере, только на выходе будет список колонок publish

Если посмотрите, какие параметры принимают методы FetchAll и FetchByColumn, то заметите ограничения. В них нельзя использовать связывание. Для простых и более сложных запросов можно использовать метод Execute, передавая ему объект класса Select. О Select, я писал ранее.

1 //тоже самое, как и в предыдущем примере
2 Select select = new Select();
3 select.From("CD");
4 select.Columns("publish");
5 select.Where("title LIKE '%jovy%'");
6 DataTable dt = db.Execute(select);

Здесь вам необходимо понять принцип создания. Предыдущий пример я чаще всего записываю в более сокращенной форме:

1 DataTable dt = db.Execute(new Select()
2     .From("CD")
3     .Columns("publish")
4     .Where("title LIKE '%jovy%'"));

Давайте рассмотрим связывание между таблицами. Задача – получить все песни, которые относятся к конкретному диску:

1 //SELECT Song.id, name FROM CD INNER JOIN Song ON CD.id = Song.cd_id WHERE CD.id = 1
2 Select select = new Select()
3     .From("CD")
4     .Columns("Song.id, name")
5     .Join("Song", "CD.id = Song.cd_id", SQLJoinTypes.INNER_JOIN) //внутреннее связывание
6     .Where("CD.id = 1");
7 DataTable dt = db.Execute(select);

У нас в таблице CD есть поле типа DATETIME. Если вы хотите сделать выборку с условием даты, то в SQLite вам придется передавать дату в формате YYYY-MM-DD. Это жутко неудобно для русскоязычных пользователей. Следующий пример решает эту проблему:

1 //задаем параметры для последующей передачи
2 ParametersCollection parameters = new ParametersCollection();
3 parameters.Add("@date", DateTime.Parse("1.1.2011"), DbType.DateTime);
4  
5 Select select = new Select()
6     .From("CD")
7     .Columns("title, publish")
8     .Where("publish < @date")
9     .Order("publish DESC")
10     .Limit(10);
11 //получить первые 10 записей, дата публикации которых была ранее 1.01.2011
12 //отсортированных в обратном порядке
13 DataTable dt = db.Execute(select, parameters);

Параметров может быть сколько угодно и они могут быть какими-угодно.

Также нужно всегда помнить, Join вы можете нанизывать, добавляя все новые и новые, остальные же операторы перезаписываются:

1 Select select = new Select()
2     .From("CD")
3     .Join(...);
4  
5 select.From("Song"); //изменится с CD на таблицу Song
6 select.Join(...); //добавляем еще одно связывание. Итого уже будет два связывания
7 string s = select.SelectCommand; //так вы всегда можете посмотреть на сформированный запрос

Свойство SelectCommand возвращает текущий сформированный запрос. Таким способом вы всегда можете создавать вложенные запросы. Пример из реальной программы:

1 Select select = new Select()
2     .From("Кадры_Состав_Должности")
3     .Columns("Код_отдела")
4     .Where(string.Format("Номер_карточки = {0} AND Назначение_дата = ({1})", cardNum,
5         new Select()
6         .From("Кадры_Состав_Должности")
7         .Columns("MAX(Назначение_дата)")
8         .Where(string.Format("Назначение_дата <= GETDATE() AND Номер_карточки = {0}", cardNum)).SelectCommand));

Как показывает практика более сложные запросы, где более одного вложения, трудно читаемы. В принципе, вас никто не заставляет использовать класс Select для построения сложного запроса. Разработчик сам решает использовать ли Select или передавать сразу сформированную строку запроса (в Execute можно сделать и так).

1 DataTable dt = db.Execute("SELECT * FROM CD");

Вы сами решает насколько глубоко вам необходимо использовать возможности класса dbFacade.

Как вы заметили, я всегда результат выборки получал в виде DataTable. Что же с ним дальше делать? Разбирать… Чаще всего для этого используется конструкция foreach:

1 DataTable dt = db.Execute("SELECT * FROM CD");
2 foreach (DataRow row in dt.Rows)
3 {
4     MessageBox.Show(row[1].ToString()); //следующая строка равносильна
5     MessageBox.Show(row["title"].ToString());
6 }

или

1 //grdMain - DataGridView
2 grdMain.DataSource = db.Execute("SELECT * FROM CD");

Для получения одной строки используется метод FetchOneRow, который также может принимать Select и, опционально, параметры. В результате вы получаете Dictionary, который содержит имена полей и их значения.

1 //формируем запрос
2 Select select = new Select()
3     .From("CD")
4     .Columns("title, publish")
5     .Join("Song", "Song.cd_id = CD.id", SQLJoinTypes.INNER_JOIN)
6     .Where("id = 1");
7  
8 //выполняем
9 Dictionary<string, object> item = db.FetchOneRow(select);
10 //далее получаем значения
11 string title = item["title"].ToString();
12 DateTime date = DateTime.Parse(item["publish"].ToString());

С выборкой закончили. В следующей статье я расскажу об удалении, вставке и изменении. Свои вопросы оставляйте в комментариях.