Доступ к данным |Доступ к данным с помощью ADO.NET | 5. Использование DataSet Дальше »
5. Использование DataSet
5.1. Использование DataSet с существующими данными
5.2. Создание DataSet программным путём
5.3. Добавление DataTable в DataSet
5.4. Добавление отношений между двумя таблицами
5.5. Установка отношений между таблицами
5.6. Добавление ограничений для DataSet
  5.6.1. ForeignKeyConstraint
  5.6.2. UniqueConstraint
5.7. Работа с событиями DataSet
5.8. Использование Typed DataSet

5. Использование DataSet

Чтобы появилась возможность использования DataSet, Вы должны включить System.Data:

using System.Data

Есть два основные способа использования объекта DataSet: в рамках существующей системы управления базой данных (database management system) или создание нового DataSet программным путём.
- Используйте существующую систему управления базы данных, например SQL Server, для заполнения таблицы в DataSet. В этом методе, используйте одну SQLDataSetCommand для таблицы, чтобы заполнить объект DataTable данными. Однако, Вы должны создать объекты DataRelation между всеми таблицами.
- Вы можете создавать DataSet программным путём, добавлять объекты DataTable к нему и затем создавать объекты DataRelation, чтобы организовать связи для каждой таблицы. Используйте программный путь, когда Вам необходимо создать DataSet в процессе выполнения программы, чтобы увидеть на экране данные, сгенерированные приложением.

В типовом решении, данные запрашиваются приложением клиента посредством URL. Когда запрос достигает соответствующего компонента промежуточного слоя, DataSet будет создан с помощью специального адаптера. После этого, DataSet конвертируется в XML документ для транспортировки назад к инициатору запроса.
В клиентском приложении данные отображаются с использованием комбинации средств управления, например, DataGrid. Пользователь может добавлять, удалять, или редактировать данные. После окончания работы с данными пользователем, DataSet снова конвертируется в документ XML для передачи назад к компоненту сервера. Компонент промежуточного слоя конвертирует документ XML назад в DataSet, и использует адаптер, чтобы попытаться применить изменения данные в системе управления базой данных. Если будут обнаружены коллизии данных, компонент сервера может урегулировать их, используя встроенные бизнес-правила. Урегулированный DataSet будет возвращён назад клиенту. После этого, DataSet может быть применён в существующий DataSet, и пользователь может продолжить с ним работу, причём, DataSet после этого будет отражать самую последнюю версию.

Потенциальная потеря точности для десятичного типа данных (Decimal)
DataSet хранит данные, используя типы, имеющиеся у COM+. Для большинства прикладных программ, они обеспечивают удобное представление информации источника данных. Однако, это представление может причинять проблему, когда тип в источнике данных - SQL decimal. Тип COM + decimal позволяет иметь максимум 28 знаков цифр, в то время как тип SQL decimal позволяет иметь 38 знаков цифр. В настоящее время, FillDataSet метод вызывает исключение, если он сталкивается с правильным типом SQL decimal, но большим, чем 28 знаковых цифр. Пока нет никакого способа получить SQL decimal больших чем 28 знаковых цифр в объекте DataSet. Если ваше приложение требует большей точности, используйте объект SQLDataReader и запрос метода GetSQLNumeric, что бы получить необходимое значение SQL decimal.

5.1. Использование DataSet с существующими данными

Рассмотрим общепринятые способы использования DataSet с существующими данными:
1. Создайте и заполните каждую таблицу в DataSet данными системы управления базой данных, используя SQLDataSetCommand или ADODataSetCommand. См. Создание простой DataSetCommand.
2. Измените данные в индивидуальных объектах DataTable, добавляя, модифицируя или удаляя объекты DataRow.
3. Вызовите метод GetChanges для создания второго DataSet, который будет показывать только изменения в данных. Метод требует один параметр, DataRowState для изменений, в которых Вы заинтересованы. Приведённый ниже пример использует метод возвращающий DataSet, содержащий только изменённые строки:

[VB]
Dim changedDataSet As DataSet
changedDataSet = ds.GetChanges(DataRowState.Modified)

[C#]
System.Data.DataSet changedDataSet;
changedDataSet = ds.GetChanges(DataRowState.Modified);

4. Проверьте ошибки во втором DataSet, исследуя его свойство HasErrors, посредством которого можно узнать, имеет ли ошибки какая-либо из таблиц в наборе.
5. Если ошибки присутствуют, проверьте свойство HasErrors каждой DataTable. Если таблица имеет ошибки, вызовите метод GetErrors класса DataTable, который возвратит массив объектов DataRow с ошибками.
6. Для каждого DataRow, исследуйте свойство RowError для того, что бы определить к каким данным это относится.
7. Урегулируйте ошибки, если это возможно.
8. Вызовите метод Merge, что бы объединить изменения во втором DataSet с первым.

[VB]
ds.Merge(changedDataSet)

[C#]
ds.Merge(changedDataSet);

9. Вызовите метод Update для SQLDataSetCommand (или ADODataSetCommand), используя объединенный DataSet как параметр.

[VB]
workDSCMD.Update (ds)

[C#]
workDSCMD.Update (ds);

10. Вызовите метод AcceptChanges для DataSet, что бы принять изменения, или альтернативный метод RejectChanges, чтобы отменить изменения.

ds.AcceptChanges

5.2. Создание DataSet программным путём

DataSet обеспечивается двумя основными конструкциями:

public DataSet()
public DataSet(string DataSetName)

Первая конструкция для пустого DataSet, вторая создаёт DataSet с указанным именем.
Следующий пример создает экземпляр DataSet:

[VB]
Dim workDataSet as DataSet
Set workDataSet As New DataSet() ' Empty DataSet.
' Or
Set workDataSet As New DataSet("CustomerOrders")

[C#]
DataSet workDataSet = new DataSet(); // Empty DataSet.
// Or
DataSet workDataSet = new DataSet("CustomerOrders");

5.3. Добавление DataTable в DataSet

ADO.NET дает Вам возможность вначале создать внешние таблицы, а затем добавлять их к существующему набору данных DataSet. (чтобы создать DataTable, см. .Net Framework SDK Создание DataTable)
Обратите внимание, для текущей версии, Вы должны добавить недавно созданную таблицу к DataSet до загрузки её данными.
Следующий пример создает DataSet (ds), добавляет новый DataTable с именем Orders и добавляет три столбца (OrderID, OrderQuantity, и CustID) к объекту DataTable. Наконец, этот код определяет столбец OrderID как первичный ключ.

[VB]
ds.Tables.Add(New DataTable("Orders"))
ds.Tables("Orders").Columns.Add("OrderID", System.Type.GetType("System.Int32"))
ds.Tables("Orders").Columns.Add("OrderQuantity", _
             System.Type.GetType("System.Int32"))
ds.Tables("Orders").Columns.Add("CustID", _
             System.Type.GetType("System.Int32"))
ds.Tables("Orders").PrimaryKey = New DataColumn(ds.Tables.Columns("Orders"), _
             ds.Tables.Columns("OrderID"))
' Or

Dim workTable As DataTable = New DataTable("Orders")
workTable.Columns.Add("OrderID", System.Type.GetType("System.Int32"))
workTable.Columns.Add("OrderQuantity", System.Type.GetType("System.Int32"))
workTable.Columns.Add("CustID", System.Type.GetType("System.Int32"))
ds.Tables("Orders").PrimaryKey = _
            New   DataColumn(ds.Tables("Orders").Columns("OrderID"))
ds.Tables.Add(workTable)

[C#]
ds.Tables.Add(new DataTable("Orders"));

ds.Tables["Orders"].Columns.Add("OrderID",
System.Type.GetType("System.Int32"));
ds.Tables["Orders"].Columns.Add("OrderQuantity",
System.Type.GetType("System.Int32"));
ds.Tables["Orders"].Columns.Add("CustID", System.Type.GetType("System.Int32"));

ds.Tables["Orders"].PrimaryKey =
new DataColumn[]{ds.Tables["Orders"].Columns["OrderID"]};

// Or

DataTable workTable = new DataTable("Orders");
workTable.Columns.Add("OrderID",
System.Type.GetType("System.Int32"));
workTable.Columns.Add("OrderQuantity",
System.Type.GetType("System.Int32"));
workTable.Columns.Add("CustID", System.Type.GetType("System.Int32"));
ds.Tables["Orders"].PrimaryKey =
new DataColumn[]{ds.Tables["Orders"].Columns["OrderID"]};
ds.Tables.Add(workTable);

5.4. Добавление отношений между двумя таблицами

Поскольку DataSet может содержать множество объектов DataTable, также должен быть способ связать все таблицы друг с другом. Это может быть необходимо для организации навигации по таблицам, и для возвращения связанных значений.
Необходимыми параметрами DataRelation являются два столбца, которые служат как первичные ключи и foreign ключи в отношениях таблиц, и имя DataRelation. Имя может использоваться для навигации, или при поиске значений.
Примечание: Отношения также могут быть построены не только по одному столбцу в таблице. Вы можете использовать массив объектов DataColumn для первичных и foreign ключей.
Представленный ниже пример предполагает, что в DataSet существуют два объекта DataTable. Обе таблицы имеют столбец по имени CustID, который служит для связи между таблицами. Пример добавляет один DataRelation к совокупности отношений объекта DataSet. Первый параметр (CustOrders) определяет имя отношений. Второй и третий параметры - объекты DataColumn, которые связывают две таблицы.

[VB]
Dim ds As DataSet = New DataSet("CustomerOrders")
' With ds do the following:
'  - add a customer table with CustID and CustName as columns.
'  - set Customers.CustID as the PrimaryKey column.
'  - add an Orders table with three columns: OrderID, CustID, and Quantity
'  - set Orders.OrderID as the PrimaryKey column.
' Add a DataRelation to the Relations collection specifying its name, and the
' appropriate DataColumn objects as arguments.
ds.Relations.Add("CustOrders", ds.Tables("Customers").Columns("CustID"), _
         ds.Tables("Orders").Columns("CustID"))

' Or
Dim dr As DataRelation = _
New DataRelation("CustOrders", ds.Tables("Customers").Columns("CustID"), _
         ds.Tables("Orders").Columns("CustID"))
ds.Relations.Add(dr)

[C#]
   DataSet ds = new DataSet("CustomerOrders");

   // With ds do the following:
   // - add a customer table with CustID and CustName as columns
   // - set Customers.CustID as Primary Key
   // - add an Orders table with three columns: OrderID, CustID, and Quantity
   // - set Orders.OrderID as primary key
  // Add a DataRelation to the Relations collection specifying its name,
  // and the appropriate DataColumn objects as arguments.

ds.Relations.Add("CustOrders",ds.Tables["Customers"].Columns["CustID"],
     ds.Tables["Orders"].Columns["CustID"]);
// Or
DataRelation dr;
dr = new DataRelation("CustOrders",ds.Tables["Customers"].Columns["CustID"],
                        ds.Tables["Orders"].Columns["CustID"]);
ds.Relations.Add(dr)

5.5. Установка отношений между таблицами

В начале, функция DataRelation должна обеспечить навигацию от одной таблицы к другой в пределах DataSet. Это позволит привязать все связанные объекты DataRow одной таблицы, по заданной, единственной DataRow из связанной с ней таблицы. Например, если дана DataRow таблицы Customers, Вы можете получить все orders относящиеся к клиенту из таблицы Orders.
Представленный ниже пример кода возвращает множество объектов DataRow (orders) из одной таблицы, используя DataRelation и единственную DataRow из другой (customers).

[VB]
Dim x() As DataRow = ds.Tables("Customers").ChildRelations("CustOrders"). _
            GetChildRows(ds.Tables("Customers").Rows(0))
Console.WriteLine("")
Console.WriteLine("Total Child records for CustOrders Relationship = " & _
               x.Count.ToString)
Console.WriteLine("Total Tables in DataSet = " & ds.Tables.Count.ToString)

[C#]
DataRow[] x = ds.Tables["Customers"].ChildRelations["CustOrders"]
    .GetChildRows(ds.Tables["Customers"].Rows[0]);

Console.WriteLine("");
Console.WriteLine("Total Child records for CustOrders Relationship = " +
x.Count.ToString());

Console.WriteLine("Total Tables in DataSet = " + ds.Tables.Count.ToString());

5.6. Добавление ограничений для DataSet

В реляционной базе данных должна обеспечиваться целостность данных. Один из путей поддержания такой целостности в ADO.NET, это добавление ограничений к таблицам. Ограничение, это автоматически исполняемое правило, которое определяет порядок действий, когда содержание строки так или иначе изменено. Есть два вида ограничений, доступных в ADO.NET: ForeignKeyConstraint и UniqueConstraint.

5.6.1. ForeignKeyConstraint

Когда значение в строке удалено или обновлено, и это значение также используется в одной или более связанных таблиц, ForeignKeyConstraint определяет то, что случается во второй таблице, которая связана с той же самой колонкой через DataRelation. Возможные действия включают:

Действие Описание
Cascade Удаление или обновление связанных строк.
SetNull Установка значений в связанных строках к null.
SetDefault Установка значений в связанных строках к значениям по умолчанию.
None No action — значения в связанных строках не затронуты.
Default Заданное по умолчанию действие для свойства, которое должно применятся при каскадном действии.

Используя ForeignKeyConstraint сначала создают ограничение, а затем устанавливают свойства DeleteRule и UpdateRule к одному из соответствующих значений, как показано в примере ниже:

[VB]
Dim fk As ForeignKeyConstraint = _
New ForeignKeyConstraint(ds.Tables("Customers").Columns("CustID"), _
ds.Tables("Orders").Columns("CustID"))
fk.DeleteRule = Cascade
fk.UpdateRule = SetDefault
' Add the constraint to the Customers table.
ds.Tables(0).Constraints("Customers").Constraints.Add(fk)

[C#]
ForeignKeyConstraint fk = new ForeignKeyConstraint(ds.Tables
["Customers"].Columns["CustID"], ds.Tables["Orders"].Columns["CustID"]);
fk.DeleteRule = Cascade;
fk.UpdateRule = SetDefault;
ds.Tables["Customers"].Constraints.Add(fk);

5.6.2. UniqueConstraint

Когда обязательно, чтобы все значения в столбце были уникальны, Вы можете добавить к DataTable UniqueConstraint. UniqueConstraint может быть назначен или для отдельного столбца, или на массив столбцов того же самого объекта DataTable.

[VB]
Dim uc As UniqueConstraint = _
New UniqueConstraint(ds.Tables("Customers").Columns.("CustID"))
' Add the constraint to the Customers table.
ds.Tables("Customers").Constraints.Add(uc)

[C#]
Data.UniqueConstraint uc = new
UniqueConstraint(ds.Tables("Customers").Columns.("CustID");
// Add the constraint to the Customers table.
ds.Tables["Customers"].Constraints.Add(uc);

5.7. Работа с событиями DataSet

DataSet обеспечивает ряд событий, которые могут быть использованы в коде пользователя. Этот события включают:
- PropertyChange
- MergeFailed
- RemoveTable
- RemoveRelation
- Добавление обработчика события (event handler) к событию.

[VB]
ds.AddOnPropertyChange(new System.ComponentModel.PropertyChangeEventHandler _
(AddressOf me.DataPropertyChange))
ds.AddOnMergeFailed(new System.Data.MergeFailedEventHandler _
(AddressOf me.DataSetMergeFailed))

Private Sub DataSetPropertyChange _
   (ByVal sender As Object, ByVal e As System.PropertyChangeEventArgs)
   MessageBox.Show("DataSet property change")
End Sub

Private Sub DataSetMegeFailed _
   (ByVal sender As Object, ByVal e As System.Data.MergeFaileedEventArgs)
   MessageBox.Show("Merge failed!")
End Sub

[C#]
ds.AddOnPropertyChange
(new System.ComponentModel.PropertyChangeEventHandler(DataSetPropertyChange));
ds.AddOnMergeFailed
(new System.Data.MergeFailedEventHandler(DataSetMergeFailed));

private void DataSetPropertyChange
   (object sender, System.PropertyChangeEventArgs e){
   MessageBox.Show("DataSet property change")}

private void DataSetMergeFailed
   (object sender, System.Data.MergeFailedEventArgs e){
   MessageBox.Show("Merge failed!")}

5.8. Использование Typed DataSet

ADO обеспечивает отложенно-связанный доступ (late bound access) к значениям в пределах его рекордсета через слабо типизированные переменные. ADO.NET обеспечивает способность обратиться к данным, содержащимся в DataSet через метафору "Strongly-Typed". Это означает, что Вы можете обращаться к таблицам и столбцам, которые являются частью DataSet через простые имена и strongly typed переменные.
Typed DataSet - класс, который происходит от DataSet. Также, он наследует все методы и свойства DataSet. Однако, в дополнение, typed DataSet обеспечивает методы "strongly-typed". На практике это означает, что Вы можете обращаться к таблицам и столбцам по имени, вместо использования collection based метода.
Например, в ADO Вы могли использовать следующий код Visual Basic, чтобы найти определенную запись в рекордсете, и изменить значение поля:

AdoRecordSet.Find("Customerid = 'ALFKI'")
AdoRecordSet.Fields("FirstName").Value = "Bob"

Для typed DataSet в ADO.NET, тот же самый результат был бы получен с помощью следующего кода:

CustomerDataSet.Customers("ALFKI").CustomerName = "Bob"

Кроме удобочитаемости кода, typed DataSet позволяет транслятору автоматически завершать строки, которые Вы пишете.
Кроме того, strongly-typed DataSet обеспечивает доступ к значениям строки как правильным strongly typed значениям. В ADO Вы работали через варианты при назначении и поиске данных. Если бы значение, которое Вы назначили, имело бы неправильный тип, ADO выдал бы ошибку во время выполнения программы. В ADO.NET, если значение - целое число, и Вы пытаетесь назначать строку, Вы получите статическую ошибку.
Учитывая схему XML, которая поддерживает XSD стандарт, Вы можете генерировать typed DataSet используя программу XSD.EXE, поставляемую с .NET Framework SDK. Синтаксис генерации DataSet следующий:

xsd.exe /d /l:C# {XSDSchemaFileName.xsd}

Где:
/D – директива, сообщающая программе о необходимости генерировать DataSet;
/l: - сообщает программе какой язык использовать. Для обозначения языка Вы можете использовать C# или VB.

Представленный ниже пример использует typed DataSet с именем customerDataSet, чтобы загрузить список customers (заказчиков) из базы данных Northwind. Как только данные загружены, используя метод FillDataSet, организуется цикл по каждому заказчику в таблице customers, используя объект typed customerRow. Здесь, Вы имеете прямой доступ к полю customerid, в противоположность доступу к этому полю через совокупность полей (fields collection).

[C#]
customerDataSet myCustDS = new customerDataSet();
SQLDataSetCommand myDSCommand = new SQLDataSetCommand("SELECT * FROM
Customers", "server=localhost;uid=sa;pwd=;database=northwind");

myDSCommand.FillDataSet(myCustDS, "Customers");

foreach(customersRow myCustomer in myCustDS.customers)
{
Console.WriteLine(myCustomer.CustomerID.ToString());
}

[VB]
Dim myCustDS as DataSet = new dataset
  
Dim myDSCommand as SQLDataSetCommand
myDSCommand = new SQLDataSetCommand("Select * from customers",
"server=localhost;uid=sa;pwd=;database=northwind")
  
myDSCommand.FillDataSet(myCustDS, "Customers")

Dim myCustomer as DataRow

For Each myCustomer in myCustDS.Tables(0).Rows
Console.WriteLine(myCustomer(0).ToString())
Next

Доступ к данным |Доступ к данным с помощью ADO.NET | 5. Использование DataSet Дальше »
Скачать электронную карту Ангарска бесплатно
Сайт управляется системой uCoz