В цикле прошлых статей я рассказал, как работать с классом 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()); |
С выборкой закончили. В следующей статье я расскажу об удалении, вставке и изменении. Свои вопросы оставляйте в комментариях.