DataSet

advertisement
Высокоуровневые методы
информатики и
программирования
Лекция 28
Отсоединенный режим работы
ADO.Net
Присоединенный режим работы
с БД
Наша программа
Читаем в цикле
используя
операцию [ ]
DataReader
ExecuteScalar()
- получаем одно
значение
ExecuteReader()
Command
Command
• SQL Select
• хранимая процедура
• SQL Insert, Update,
Delete
• хранимая процедура
ExecuteNonQuery()
Connection
БД : MS SQL Server, Oracle,
MS Access, Foxpro, DBase и т.п.
Отсоединенный режим работы с
БД
Использование классов
ADO.NET
ExecuteReader
DataReader
Command
Connection
Read
Update, Insert, Delete
Data
Base
DataAdapter
Provider
ExecuteXx
x
Client
Program
Fill
Update
DataSet
Компьютер пользователя
SQL Server
организации
Класс DataSet
• Объекты класса DataSet позволяют создать базу данных в
оперативной памяти.
– Данные извлекаются из базы данных и сохраняются в объекте
DataSet.
– Объект DataSet содержит набор данных отсоединенных от БД.
– Затем программа может изменять эти данные
• Обновления сделанные в DataSet должны быть занесены
обратно в БД для того, чтобы сохранить их постоянно.
• Класс DataSet является одним для всех провайдеров по
работе с БД.
• Объекты класса DataSet включают объекты DataTable
(таблицы данных) и DataRelation (связи между таблицами).
• Для заполнения объекта DataSet используется класс
DataAdapter из провайдера.
Наша программа
DataTable
Метод Fill()
DataTable
DataTable
DataSet
Метод Update()
DataAdapter
DataAdapter
Connection
DataAdapter
Command
Command
Command
Command
ExecuteNonQuery()
БД : MS SQL Server, Oracle,
MS Access, Foxpro, DBase и т.п.
Конструкторы класса DataSet
• DataSet ds = new DataSet();
• DataSet ds = new DataSet("MyDataSet");
Структура класса DataSet
DataSet
.Tables[...]
DataTable
DataTable
schema
.Columns[...]
.Columns[..]
DataColumn DataColumn
.Rows[...]
.Rows[..]
DataRow
DataRow
.DefaultView
...
.Relations[...]
...
DataView
DataRelation
DataRelation
данные
Свойства класса DataSet
Основные:
• Tables – коллекция таблиц DataTable
• Relations – коллекция отношений DataRelation
Дополнительные свойства:
• ExtendedProperties – коллекция дополнительных свойств (имя, значение)
• CaseSensitive – указывает, будет ли при сравнении строк в DataTable
объектах учитываться регистр (большие и маленькие символы).
• DataSetName – дружественное имя данного DataSet. Обычно задается в
конструкторе класса.
• EnforceConstraints – получает или задает значение указывающее на то, будут
ли учитываться ограничивающие правила (constraint rules) при попытке
выполнить любую операцию обновления.
• HasErrors – получить значение указывающее на наличие ошибок в любой
строке любой таблицы DataTables данного DataSet.
• RemotingFormat – позволяет определить то, как будет сериализоваться
содержание DataSet (binary или XML).
Основные методы DataSet
•
•
•
•
•
•
•
•
•
•
•
Clear() – полное удаление всех записей во всех DataTable таблицах DataSet.
Merge() – слияние данного DataSet с указанным DataSet.
GetChildRelations() – получить коллекцию дочерних отношений указанной
таблицы.
GetParentRelations() - получить коллекцию родительских отношений
указанной таблицы.
HasChanges() – определить, изменился ли DataSet, включая новые,
удаленные или измененные записи (rows).
AcceptChanges() – принятие (commits) всех изменений сделанных в этом
DataSet с момента загрузки в него данных или последнего вызова метода
AcceptChanges().
RejectChanges() – отменить все изменения, сделанные в данном DataSet с
момента его создания или последнего вызова метода AcceptChanges().
ReadXml() – чтение XML данных из потока (файла, оперативной памяти, или
сети) в DataSet.
ReadXmlSchema() – чтение структуры
WriteXml() – записать содержание DataSet в поток.
WriteXmlSchema() – записать структуру DataSet в поток.
Создание и заполнение таблицы с
помощью DataAdapter
SqlConnection conn = new SqlConnection(conString);
SqlDataAdapter da = new SqlDataAdapter(
"SELECT pub_id, pub_name FROM Publishers", conn);
DataSet pubsDataSet = new DataSet("Pubs");
da.Fill(pubsDataSet, "publishers");
Использование классов
ADO.NET
ExecuteReader
DataReader
Command
Connection
Data
Base
Read
Select
Update, Insert, Delete
DataAdapter
Provider
ExecuteXx
x
Client
Program
Fill
Update
DataSet
Компьютер пользователя
SQL Server
организации
Класс DataAdapter
• Для организации взаимодействия DataSet с БД.
• Организует взаимодействие одной таблицы DataSet с
базой данных
• Свойства
–
–
–
–
SelectCommand содержит SQL SELECT оператор
InsertCommand содержат SQL INSERT
UpdateCommand содержат SQL UPDATE
DeleteCommand содержат SQL DELETE операторы
• Методы
– Fill(ds) использует соединение для заполнения DataSet
данными
• Первый параметр – объект DataSet
• Второй (необязательный) – название создаваемой таблицы
– Update() посылает исправленные в DataSet данные в БД
• Параметр – объект DataSet
Конструкторы класса DataAdapter
• Конструктор класса DataAdapter является перегруженным:
– без параметров
SqlDataAdapter da = new SqlDataAdapter();
– с одним параметром – объектом Command:
SqlDataAdapter da = new SqlDataAdapter(cmd);
– с двумя параметрами – SQL оператором и объектом Connection:
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
– с двумя параметрами – SQL оператором и строкой соединения:
SqlDataAdapter da = new SqlDataAdapter(sql, connString);
• Параметры:
–
–
–
–
conn – объект Connection;
connString – строка соединения.
sql – оператор языка SQL;
cmd – объект Command;
Методы Fill() и Update()
• Метод int Fill():
– int Fill (DataSet ds) – в DataSet создается и заполняется
данными таблица БД (к данной таблице можно обращаться
только по номеру);
– int Fill (DataTable dt) – заносит в таблицу схему и данные;
– int Fill (DataSet ds, string srcTable) – в DataSet создается и
заполняется данными таблица с именем srcTable (к данной
таблице можно обращаться только по имени);
• Метод int Update():
– int Update(DataSet ds) – в БД сохраняются изменения всех
таблиц DataSet;
– int Update(DataSet ds, string srcTable) – в БД сохраняются
изменения таблицs с данным именем;
– int Update(DataRow[] drs) – в БД сохраняются изменения
сделанные в записях из массива.
Последовательность работы с
DataAdapter
• Создать объект Connection.
• Создать экземпляр класса и задать объект Command
с SQL командой Select.
• Создать объект класса CommandBuilder и построить
в DataAdapter команды Insert, Update и Delete.
• Вызвать для DataAdapter метод Fill(), в который
передать объект DataSet.
• Выполнять работу с DataSet
• После окончания работы вызвать для DataAdapter
метод Update(), в котором передается
использованный объект DataSet.
Пример
SqlDataAdapter ad = new SqlDbDataAdapter
(“select ProductID, ProductName, UnitPrice from Products”, conn);
SqlCommandBuilder bld = new SqlCommandBuilder (ad);
DataSet ds = new DataSet();
ad.Fill (ds) ; // можно задать и другое имя таблиц - , “Products”);
DataTable tbl = ds.Tables["Products"];
for (int i = 0; i < tbl.Rows.Count; i++)
{
Console.WriteLine("id={0};name={1};цена={2}", tbl.Rows[i][0],
tbl.Rows[i][1], tbl.Rows[i][2]);
}
Класс CommandBuilder
• Данный класс используется для упрощения создания
набора SQL команд.
• Может применяться, когда используется оператор Select
для одной таблицы БД.
• По заданной в DataAdapter SQL команде select создаются
соответствующие ей команды
– InsertCommand содержат SQL INSERT
– UpdateCommand содержат SQL UPDATE
– DeleteCommand содержат SQL DELETE операторы
• Эти команды требуются для выполнения метода Update
(перенесение всех изменений из DataSet в БД).
• Для создания новых команд нужно создать объект класса
CommandBuilder и передать ему в качестве параметра
объект DataAdapter.
– Например:
SqlCommandBuilder св = new SqlCommandBuilder(da);
Пример использования объекта
DataAdapter
// создаем DataAdapter
SqlDataAdapter da = new OleDbDataAdapter
(“select ProductID, ProductName, UnitPrice from Products”, conn);
// автоматически строим команды Insert, Update,Delete
SqlCommandBuilder cb = new SqlCommandBuilder(oDA);
DataSet ds = new DataSet();
da.Fill(ds);
decimal newPrice = (decimal) tbl.Rows[0][“UnitPrice "] + 1.0M;
tbl.Rows[0]["UnitPrice"] = newPrice;
da.Update(ds, “Products”);
Класс DataTable
• Полное имя класса System.Data.DataTable.
• Концептуально аналогичен таблице в БД.
• Содержит две коллекции:
– строк Rows;
– столбцов Columns – объекты с описаниями полей записей.
• Может использоваться, для представления самостоятельной
таблицы или таблицы в DataSet.
• Для получения значений колонок таблицы можно
использовать индексаторы tbl[i][j], где
– i – номер строки;
– j – номер колонки (можно задать и название колонки).
• Например:
DataTable tbl;
…
int n = tbl.Rows[i][j]
Класс DataColumn
•
Ссылки на объекты данного класса можно получить из таблицы
Columns с помощью индекса или с помощью названия колонки:
DataSet ds = new DataSet();
// заполняем
DataColumn col = ds.Columns["ContactName"];
DataColumn col = ds.Columns[2];
•
Для получения в записи Row значению поля из колонки col можно
получить следующим образом:
DataRow r = ds.Table[0].Rows[0];
r[0] = 1;
r[“CustomerID”] = 1;
DataColumn col = ds.Columns[“CustomerID"];
r[col] = 1;
Класс записей DataRow
• Объект класса DataRow Запись (строка, data row) представляет
собой запись данных из таблицы, в коллекции которой он
хранится.
• Записям таблицы DataTable хранятся в коллекции Rows.
• Записи можно программно
– добавлять к коллекции(add),
– обновлять (update),
– удалять из коллекции (delete).
• Для получения доступа к конкретной записи используется
операция [ ] с индексом.
– Например, если dt является таблицей данных, то вторую
запись можно получить следующим образом:
DataRow row = dt.Rows[2];
Класс DataRelation
•
Для создания связи между первичным ключом и внешним ключом нужно
создать объект класса DataRelation.
– Например:
DataColumn ParentColumn = ds.Tables[“Customers”].Columns[“CustomerID”];
DataColumn ChildColumn = ds.Tables[“Orders”].Columns[“CustomerID”];
DataRelation myRel = DataRelation(“CusOderRel”, ParentColumn, ChildColumn);
•
Затем созданное отношение между ключами нужно сохранить в
коллекции Relations объекта DataSet, который содержит первичный ключ.
– Например:
myDS.Relations.Add(myRel);
•
Объект Row имеет методы
–
–
GetChildRows(“имя таблицы”)
GetParentRow(“имя таблицы”)
Пример задания связи между
записями
• Задание связи Relationship с именем "RelOrdDet" между полями
Orders.OrderID и OrderDetails. OrderID
using System.Data;
…
DataRelation relOrdDet;
DataColumn colMaster2;
DataColumn colDetail2;
colMaster2 = ds.Tables["Orders"].Columns["OrderID"];
colDetail2 = ds.Tables["OrderDetails"].Columns["OrderID"];
relOrdDet = new DataRelation("RelOrdDet",colMaster2,colDetail2);
ds.Relations.Add(relOrdDet);
• Связывание данных с помощью Relationship
grdOrderDetails.DataSource = dsView;
grdOrderDetails.DataMember = "Customers.RelCustOrd.RelOrdDet";
Объект DataSet
Работа с данными в DataSet
•Чтение данных
•Изменение данных
•Добавление записей в данные
•Сортировка записей
•Удаление данных
Выборка массива записей из таблицы
DataTable
• Для фильтрации и сортировки записей в
таблице используется метод Select()
public DataRow[ ] Select(
string filterExpression,
string sort);
// условие выборки
// сортировка
• Например:
string filterStr = “id = 1”;
string sortStr = “ . . . ”;
DataRow[] sotr = emploees.Select(filterStr, sortStr);
if(sotr.Length != 0)
{ …. }
Добавления записи в таблицу
DataTable
• Для добавления новой записи к таблице
необходимо выполнить следующие действия:
– Создать с помощью метода NewRow() класса DataTable
пустую запись имеющую структуру, соответствующую
данной таблице (число и тип полей).
• Например:
DataRow row = tbl.NewRow ();
– Занести данные в поля созданной записи.
• Например:
row[“id”] = 44;
row[“authir”] = “Терентьев И.А.”;
row[“year”] = 2003;
– Сохранить новую запись в коллекции Rows таблицы.
• Например:
tbl.Rows.Add(row);
Пример добавления записи в таблицу
DataTable
// создаем dataset
DataSet ds = new DataSet();
// заполняем dataset данными для таблицы MyBooks
…
// получаем ссылку на таблицу MyBooks
DataTable tbl = ds.Tables[“MyBooks”];
// создаем новую запись для данной таблицы
DataRow row = tbl.NewRow ();
// задаем значения полей
row[“id”] = 44;
row[“authir”] = “Терентьев И.А.”;
row[“year”] = 2003;
// заносим новую запись в таблицу
tbl.Rows.Add(row);
// сохраняем изменения в базу данных
ad.Update(tbl);
Удаление записей из таблицы
DataTable
• Для удаления записей можно использовать метод
Remove() коллекции Rows:
– Например:
DataRow row = table.Rows[5];
table.Rows.Remove(row);
• Для удаления записей можно использовать метод
Delete() объекта DataRaw:
– Например:
DataRow row = table.Rows[5];
row.Delete();
Класс представление таблицы
DataView
•
•
Объект DataView это просмотр записей в объекте DataTable, с помощью
фильтра и сортировки.
Конструктор класса DataView:
// myDT – таблица данных
DataView myDV = new DataView(myDT);
•
Свойство сортировки элементов Sort:
•
Свойство отбора элементов (фильтр) RowFilter задается в виде условия, в
представление будут выбираться только элементы, которые удовлетворяют
данному условию.
– myDV.Sort = “имя поля”;
– Можно несколько полей (через запятую)
– Можно в обратном порядке (DESC)
– Например:
myDV.Sort = “ID, Name”;
–
Например
myDV.RowFilter = “City = ‘Tomsk’”;
•
Объект DataView можно связать с элементами графического интерфейса,
например, DataGridView.
–
Например:
DataGridView dgv = new DataGridView();
dgv.DataSource = myDV;
Пример создания и связывания
DataView с ЭУ DataGridView
//создаем DataView
DataView view = new DataView(employee);
//задаем правило отбора
view.RowFilter = "LastName like 'A%' and Salary > 15";
//задаем порядок сортировки
view.Sort = "LastName ASC, FirstName ASC, Salary DESC";
//связываем элемент управления с DataView
dgv.DataSource = view;
Совпадение изменений БД
•
•
•
•
•
•
•
•
При занесении изменений в БД могут возникать конфликты между разными
пользователями. Например, два пользователя могут пытаться изменить одну и ту же
запись в БД.
Как БД разрешает такие конфликты? Данные какого пользователя должны заносить
первыми, какого – вторыми, и должны ли они вовсе заноситься?
Ответ не совсем однозначен. Все зависит от множества факторов.
However, ADO.NET provides a fundamental level of concurrency control that’s designed to
prevent update anomalies. The details are beyond the scope of this book, but the following
is a good conceptual start.
Basically, a dataset marks all added, modified, and deleted rows. If a row is propagated to
the database but has been modified by someone else since the dataset was filled, the data
manipulation operation for the row is ignored. This technique is known as optimistic
concurrency and is essentially the job of the data adapter.
When the Update method is called, the data adapter attempts to reconcile all changes.
This works well in an environment where users seldom contend for the same data.
This type of concurrency is different from what’s known as pessimistic concurrency, which
locks rows upon modification (or sometimes even on retrieval) to avoid conflicts. Most
database managers use some form of locking to guarantee data integrity.
Disconnected processing with optimistic concurrency is essential to successful multitier
systems. How to employ it most effectively given the pessimistic concurrency of DBMSs is
a thorny problem. Don’t worry about it now, but keep in mind that many issues exist, and
the more complex your application, the more likely you’ll have to become an expert in
concurrency.
Download