Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции OOP c#.doc
Скачиваний:
44
Добавлен:
22.09.2019
Размер:
3.38 Mб
Скачать

4.12. DataSet и схема рассоединенного набора данных

Описав в предыдущих параграфах основные компоненты набора данных DataSet, рассмотрим этот класс более подробно. Начнем с таблицы свойств класса DataSet.

Таблица 31

Свойства класса DataSet

Имя свойства

Описание

CaseSensitive

Определяет, учитывается ли регистр при поиске строк

DataSetName

Строка с именем набора данных

EnforceConstraints

Определяет, обеспечивает ли DataSet выполнение определенных на нем ограничений

ExtendedProperties

Коллекция пользовательских свойств набора данных

HasErrors

Указывает, содержит ли набор данных ошибки

Locale

Свойство имеет тип CultureInfo и определяет региональные параметры, используемые набором данных при сравнении строк

Relations

Коллекция отношений, связывающих таблицы из набора данных

Tables

Возвращает коллекцию таблиц набора данных

Большинство свойств в особых пояснениях не нуждается, ибо, по сути, является аналогом свойств таблицы, но для всего набора данных. Свойство Relations содержит коллекцию связей между таблицами и является часть описания схемы данных. Если значение свойства EnforceConstraints установить в false, то при загрузке информации в DataSet данные не будут проверяться на соответствие ограничениям. Это повышает производительность.

В таблице 32 перечислены методы набора данных:

Таблица 32

Методы класса DataSet

Имя метода

Описание

AcceptChanges()

Метод фиксирует все изменения данных, которые были проделаны с момента предыдущего вызова AcceptChanges()

Clear()

Уничтожаются все строки всех таблиц набора данных

Clone()

Метод клонирует структуру набора и возвращает пустой набор

Copy()

Метод клонирует и структуру, и данные набора

GetChanges()

Возвращает новый DataSet с идентичной схемой, содержащий измененные строки и таблицы оригинального объекта DataSet

GetXml()

Возвращает содержимое объекта DataSet в виде XML-строки

GetXmlSchema()

Возвращает схему объекта DataSet в виде XML-строки

HasChanges()

Возвращает логическое значение, указывающее, содержат ли строки из состава DataSet отложенные изменения

Merge()

Осуществляет слияние данных из другого объекта DataSet, DataTable или массива объектов DataRow и данных текущего объекта DataSet

ReadXml()

Читает содержимое DataSet в XML-формате из файла, Stream, TextReader или XmlReader

ReadXmlSchema()

Работает как ReadXml(), но читает только схему DataSet

RejectChanges()

Метод отменяет изменения, которые еще не зафиксированы вызовом AcceptChanges()

Reset()

Восстанавливает оригинальное состояние DataSet

WriteXml()

Записывает содержимое DataSet в XML-формате в файл, Stream, TextWriter или XmlWriter

WriteXmlSchema()

Работает как WriteXml(), но записывает только схему DataSet

Рассмотрим, как вручную задать схему набора данных. Напомним, что правильная схема включает тип и имя отдельных столбцов таблицы, ограничения на столбцы и связи между таблицами. Будем создавать схему для таблиц Artists и Disks из базы CD_Rent.

Вначале создадим объекты, соответствующие столбцам и таблицам, и поместим столбцы в таблицы:

DataColumn id_artists = new DataColumn("id", typeof(int));

DataColumn name = new DataColumn("name", typeof(string));

DataTable Artists = new DataTable("Artists");

Artists.Columns.Add(id_artists);

Artists.Columns.Add(name);

DataColumn id_disks = new DataColumn("id", typeof(int));

DataColumn title = new DataColumn("title", typeof(string));

DataColumn artist_id = new DataColumn("artist_id",

typeof(int));

DataColumn release_year=new DataColumn("release_year",

typeof(string));

DataTable Disks = new DataTable("Disks");

Disks.Columns.Add(id_disks);

Disks.Columns.Add(title);

Disks.Columns.Add(artist_id);

Disks.Columns.Add(release_year);

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

id_artists.AllowDBNull = false;

name.AllowDBNull = false;

id_disks.AllowDBNull = false;

title.AllowDBNull = false;

name.MaxLength = 50;

title.MaxLength = 50;

release_year.MaxLength = 4;

Перейдем к работе с таблицами. Как и в реляционных база данных, один или несколько столбцов таблицы DataTable могут исполнять роль первичного ключа. Первичный ключ должен быть уникальным в пределах таблицы. Свойство таблицы PrimaryKey служит для получения или установки массива столбцов, формирующих первичный ключ. Если столбец является частью первичного ключа, его свойство AllowDBNull автоматически устанавливается в false. Установим первичные ключи наших таблиц:

DataColumn[] Artists_PK = new DataColumn[1] {id_artists};

Artists.PrimaryKey = Artists_PK;

DataColumn[] Disks_PK = new DataColumn[1] {id_disks};

Disks.PrimaryKey = Disks_PK;

Таблица поддерживает свойство Constraints – набор ограничений таблицы. Значением данного свойства является коллекция объектов класса Constraint. Класс Constraint – абстрактный базовый класс, имеющий два производных класса: ForeignKeyConstraint и UniqueConstraint.

Класс UniqueConstraint – это класс, при помощи объектов которого реализуется концепция уникальности значений полей строки. Основными свойствами этого класса является массив столбцов Columns, имя ограничения ConstraintName и булево свойство IsPrimaryKey, которое показывает, представляет ли данное ограничение первичный ключ таблицы. Ограничение вида UniqueConstraint автоматически добавляется в таблицу при создании первичного ключа. Это же ограничение появляется, если в таблицу добавляется столбец с установленным свойством Unique.

Так как в нашем примере мы уже создали первичные ключи таблиц, то их коллекции Constraints не пусты. Изменим имя ограничения в одной из таблиц и добавим ограничение для столбца name таблицы Artists, полагая значения в этом столбце уникальными:

Artists.Constraints[0].ConstraintName = "Primary Key";

UniqueConstraint uc = new UniqueConstraint("Unique Name",

new DataColumn[]{name});

Artists.Constraints.Add(uc);

Класс ForeignKeyConstraint служит для описания внешних ключей таблицы. Его основные свойства перечислены в таблице 33.

Таблица 33

Основные свойства класса ForeignKeyConstraint

Имя свойства

Описание

AcceptRejectRule

Определяет, каскадируются ли результаты вызова методов AcceptChanges() и RejectChanges() родительского объекта DataRow в дочерние строки

Columns

Возвращает столбцы дочерней таблицы, составляющие ограничение

ConstraintName

Имя ограничения

DeleteRule

Определяет, каскадируются ли удаление родительского объекта DataRow в дочерние строки

ExtendedProperties

Набор динамических свойств

RelatedColumns

Столбцы родительской таблицы, составляющие ограничение

RelatedTable

Родительская таблица ограничения

Table

Дочерняя таблица ограничения

UpdateRule

Управляет каскадированием изменений родительской строки в дочерние строки

Свойства AcceptRejectRule, DeleteRule и UpdateRule управляют порядком каскадирования изменений родительской строки в дочерние строки. Свойство AcceptRejectRule принимает значение из одноименного перечисления. Значение этого свойства по умолчанию – None: вызов метода AcceptChanges() или RejectChanges() объекта DataRow не сказывается на дочерних строках последнего. Если задать свойству AcceptRejectRule значение Cascade, изменения каскадируются в дочерние строки, определенные объектом ForeignKeyConstraint.

Свойства DeleteRule и UpdateRule функционируют аналогичным образом, но принимают значения из перечисления Rule. Значение этих свойств по умолчанию – Cascade, т. е. изменения родительской строки каскадируются в дочерние строки. Например, при вызове метода Delete() родительского объекта DataRow вы неявно вызываете и метод Delete() его дочерних строк. Точно так же, редактируя значение поля ключа родительского объекта DataRow, вы неявно изменяете содержимое соответствующих полей дочерних строк. Если каскадировать изменения не требуется, задайте свойствам DeleteRule и UpdateRule значение None. Можно также задать им значение SetNull или SetDefault. В первом случае при изменении или удалении содержимого родительской строки соответствующим полям дочерних строк задаются значения NULL, а во втором – их значения по умолчанию.

Обычно нет необходимости создавать объекты класса ForeignKeyConstraint вручную. Они генерируются автоматически при добавлении связи между таблицами.

Связь между таблицами представлена объектом класса DataRelation. Большинство свойств DataRelation доступно только для чтения. Задать их значение можно средствами конструкторов объекта DataRelation. В таблице 34 перечислены наиболее часто используемые свойства.

Таблица 34

Свойства класса DataRelation

Имя свойства

Описание

ChildColumns

Свойство возвращает массив, содержащий объекты DataColumn из дочернего объекта DataTable

ChildKeyConstraint

Указывает ограничение FOREIGN KEY в дочерней таблице

ChildTable

Указывает дочернюю таблицу связи

DataSet

Набор данных, в котором находится объект DataRelation

ExtendedProperties

Набор динамических свойств

Nested

Логическое значение. Указывает, нужно ли преобразовывать дочерние строки в дочерние элементы при записи содержимого DataSet в XML-файл

ParentColumns

Родительские столбцы, определяющие отношение

ParentKeyConstraint

Указывает ограничение UNIQUE в родительской таблице

ParentTable

Указывает родительскую таблицу

RelationName

Строка с именем отношения

При создании объекта DataRelation следует указать его имя, чтобы объект удалось найти в наборе; кроме этого, необходимо указать родительский и дочерний столбцы, на которых будет основано отношение. Чтобы упростить создание связей, класс DataRelation предоставляет отдельные конструкторы, принимающие как объекты DataColumn, так и массивы таких объектов.

Вернемся к нашему примеру. Создадим рассоединенный набор данных и поместим в него таблицы:

DataSet CD_Rent = new DataSet("CD_Rent_Part");

CD_Rent.Tables.Add(Artists);

CD_Rent.Tables.Add(Disks);

Между таблицами Artists и Disks существует связь по внешнему ключу. А именно, таблица Disks является дочерней для таблицы Artists, так как значения поля artist_id – это значения первичного ключа таблицы Artists. Создадим объект DataRelation, описывающий эту связь:

// Используем самый простой конструктор, который устанавливает

// имя отношения, родительский и дочерний столбцы отношения

DataRelation Artists_to_Disks = new DataRelation(

"Artists_to_Disks",

id_artists, artist_id);

// Добавим отношение в набор данных

CD_Rent.Relations.Add(Artists_to_Disks);

После выполнения данного кода коллекция Constraints объекта Artists будет содержать два отношения с именами Primary Key и Unique Artist Name (оба – класса UniqueConstraint). Коллекция Constraints объекта Disks будет также содержать два отношения. Одно – с именем Constraint1 типа UniqueConstraint, второе – с именем Artists_to_Disks типа ForeignKeyConstraint. Создание схемы данных можно считать завершенным. При желании можно добавить обработчики событий в наши таблицы.

При помощи метода адаптера WriteXmlSchema() созданную схему можно сохранить в XML-файле (правильным расширеним файла является *.xsd, так как схема сохраняется в виде XSD-описания).