В цикле прошлых статей я рассказал, как работать с классом 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(); |
Самый простой запрос:
2 |
DataTable dt = db.FetchAll("CD"); |
Чуть сложнее:
2 |
DataTable dt = db.FetchAll("CD","title LIKE '%jovy%'"); |
На самом деле метод FetchAll используется редко. Если у вас много полей, а получить необходимо лишь пару, то лучше использовать метод FetchByColumn:
2 |
DataTable dt = db.FetchByColumn("CD", "publish", "title LIKE '%jovy%'"); |
Если посмотрите, какие параметры принимают методы FetchAll и FetchByColumn, то заметите ограничения. В них нельзя использовать связывание. Для простых и более сложных запросов можно использовать метод Execute, передавая ему объект класса Select. О Select, я писал ранее.
2 |
Select select = new Select(); |
4 |
select.Columns("publish"); |
5 |
select.Where("title LIKE '%jovy%'"); |
6 |
DataTable dt = db.Execute(select); |
Здесь вам необходимо понять принцип создания. Предыдущий пример я чаще всего записываю в более сокращенной форме:
1 |
DataTable dt = db.Execute(new Select() |
4 |
.Where("title LIKE '%jovy%'")); |
Давайте рассмотрим связывание между таблицами. Задача – получить все песни, которые относятся к конкретному диску:
2 |
Select select = new Select() |
4 |
.Columns("Song.id, name") |
5 |
.Join("Song", "CD.id = Song.cd_id", SQLJoinTypes.INNER_JOIN) |
7 |
DataTable dt = db.Execute(select); |
У нас в таблице CD есть поле типа DATETIME. Если вы хотите сделать выборку с условием даты, то в SQLite вам придется передавать дату в формате YYYY-MM-DD. Это жутко неудобно для русскоязычных пользователей. Следующий пример решает эту проблему:
2 |
ParametersCollection parameters = new ParametersCollection(); |
3 |
parameters.Add("@date", DateTime.Parse("1.1.2011"), DbType.DateTime); |
5 |
Select select = new Select() |
7 |
.Columns("title, publish") |
8 |
.Where("publish < @date") |
13 |
DataTable dt = db.Execute(select, parameters); |
Параметров может быть сколько угодно и они могут быть какими-угодно.
Также нужно всегда помнить, Join вы можете нанизывать, добавляя все новые и новые, остальные же операторы перезаписываются:
1 |
Select select = new Select() |
7 |
string s = select.SelectCommand; |
Свойство SelectCommand возвращает текущий сформированный запрос. Таким способом вы всегда можете создавать вложенные запросы. Пример из реальной программы:
1 |
Select select = new Select() |
2 |
.From("Кадры_Состав_Должности") |
4 |
.Where(string.Format("Номер_карточки = {0} AND Назначение_дата = ({1})", cardNum, |
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) |
4 |
MessageBox.Show(row[1].ToString()); |
5 |
MessageBox.Show(row["title"].ToString()); |
или
2 |
grdMain.DataSource = db.Execute("SELECT * FROM CD"); |
Для получения одной строки используется метод FetchOneRow, который также может принимать Select и, опционально, параметры. В результате вы получаете Dictionary, который содержит имена полей и их значения.
2 |
Select select = new Select() |
4 |
.Columns("title, publish") |
5 |
.Join("Song", "Song.cd_id = CD.id", SQLJoinTypes.INNER_JOIN) |
9 |
Dictionary<string, object> item = db.FetchOneRow(select); |
11 |
string title = item["title"].ToString(); |
12 |
DateTime date = DateTime.Parse(item["publish"].ToString()); |
С выборкой закончили. В следующей статье я расскажу об удалении, вставке и изменении. Свои вопросы оставляйте в комментариях.