Каждый объект DataTable (Таблица данных) содержит коллекцию объектов Da-taRow. Каждый такой объект представляет строку таблицы. Добавление нового объекта DataRow влияет на ограничения объекта DataColumn (мы предполагаем, что свойство Enf orceConstraints объекта DataSet (Набор данных) имеет значение true (истина)).
Первичные ключи
Существует несколько типов ограничений. Первичный ключ — уникальный ключ для строк таблицы. Другие ограничения единственности определяют единственность каждого значения в столбце (или столбцах). Внешний ключ используется для обозначения того, что значения в столбце являются первичными ключами для другой таблицы объекта DataSet (Набор данных). Первичный ключ объекта DataTable (Таблица данных) является свойством:
// Определить РК для таблицы BookCategories DataColumn *bookcategoriesPK [] =
new DataColumn*[2]; bookcategoriesPK[0] = en; bookcategoriesPK[l] = loc; bookcategories->PrimaryKey = bookcategoriesPK;
// Определить РК для таблицы Authors (Авторы) DataColumn *authorsPK [] =
new DataColumn*[1]; authorsPK[0] = auid; authors->PrimaryKey = authorsPK; // авторы
// Определить РК для таблицы Books (Книги) DataColumn *booksPK [] =
new DataColumn*[1]; booksPK[0] = ISBN; books->PrimaryKey = booksPK; // книги
Ограничения
Для работы со всеми ограничениями помимо первичных ключей используются абстрактный базовый класс Constraint (Ограничение) и его производные классы: UniqueConstraint и ForeignKeyConstraint. Базовый класс обеспечивает возможность помещения ограничения в коллекцию ограничений таблицы. Первичный ключ также регистрируется в этой коллекции как ограничение единственности с именем, генерируемым системой. Для определения, является ли ограничение первичным ключом, используется свойство UniqueConstraint::IsPrimaryKey.
Определим уникальность значений столбца Category таблицы Categories (Категории). Так как последний аргумент метода Add (Добавить) имеет значение false (ложь), это ограничение не будет первичным ключом таблицы. Для этой таблицы мы не определяем первичного ключа, а задаем только ограничения единственности. Вообще говоря, задавать ограничения для значений таблицы не обязательно. Хотя это и нарушает правила реляционной целостности, никто не заставляет вас использовать объект DataSet (Набор данных) реляционным способом. // Определим ограничение единственности // для таблицы Categories (Категории) categones->Constraints->Add ( // категории-> Ограничениям Добавить
"Unique CategoryName Constraint",
// "Уникальное ограничение CategoryName ",
categoryname,
false); // ложь
При использовании внешнего ключа можно определить действия, которые следует выполнить при изменении первичного ключа, с которым он связан. Выбор здесь стандартен: None (Ничего), Cascade (Каскад), SetNull. Для установки значения, принимаемого по умолчанию для этого параметра (он описывается в свойстве Def aultValue объекта DataColumn), используется метод SetDefault. Эти параметры могут быть определены как для условий обновления, так и для условий удаления данных.
В нашем примере внешний ключ определяется таким образом, чтобы все идентификаторы авторов, содержащиеся в таблице Books (Книги), были описаны также и в таблице Authors (Авторы). Другими словами, у каждой книги, зарегистрированной в базе, есть автор, который также зарегистрирован в этой же базе. Мы назвали это ограничение '"Authors->Books". При изменении идентификатора автора правила обновления данных вынуждают объект DataSet (Набор данных) изменить этот идентификатор и во всех остальных строках таблиц на новое значение. Когда идентификатор удаляется, значение для этого идентификатора в строках, описывающих книги, будет установлено пустым.
Если при этом свойство DeleteRule имеет значение Cascade (Каскад), то каскадное удаление будет выполнено для всех таких строк из таблицы Books (Книги). Свойство Ас-ceptRejectRule используется при транзакционном изменении объекта DataSet (Набор данных) и будет рассмотрено ниже. Значение этого свойства определяет, что произойдет при вызове метода AcceptChanges объектов DataSet (Набор данных), Da-taRow или DataTable (Таблица данных). В нашем примере изменения будут произведены последовательно со всеми данными. Другое возможное значение этого свойства — None (не совершать никаких действий).
// Определить FK для таблицы Books (Книги) // (Authorld должен быть в таблице Authors (Авторы)) DataColumn *bookauthorFK [] =
new DataColumn*[1]; bookauthorFK[0] = booksauid; ForeignKeyConstraint *fk =
new ForeignKeyConstraint(
"Authors->Books", authorsPK, bookauthorFK); // Авторы-> Книги
fk->AcceptRe;jectRule = AcceptRejectRule::Cascade; // Каскад fk->DeleteRule = Rule::SetNull; fk->UpdateRule = Rule:rCascade; // Каскад books->Constraints->Add(fk); // книги-> Ограничениям Добавить
Связи между данными
Кроме ограничений для данных, можно задавать связи между ними, для хранения которых используется коллекция DataRelation объекта DataSet (Набор данных). Связи соединяют таблицы таким образом, что вы можете перемещаться от предка к потомку и наоборот. При добавлении связи в коллекцию ограничений автоматически добавляется и соответствующий внешний ключ.
В нашем примере таблица Categories (Категории) сделана предком таблицы Book-Categories (Категории книг) через столбцы Categories (Категории) и CategoryName. Оба столбца, между которыми определяется связь, должны содержать данные одного типа. Эту связь можно использовать для нахождения строк в таблице-потомке или строки в таблице-предке по значению поля, соответствующего связанному столбцу. В нашем примере необходимо также установить связь между столбцами, описывающими номер книги в Библиотеке Конгресса в таблицах Books (Книги) и BookCategory.
// Установим связь между столбцом Categories (Категории) // в таблице BookCategories (Категории книг) и
// столбцом Categories (Категории) в таблице Categories (Категории) ds->Relations->Add( // Отношения-> Добавить
"Category->BookCategories Relation",
// "Категория-> Отношение BookCategories ",
categoryname,
en) ;
// Установим связь между столбцом Library of Congress Number // (Номер книги в Библиотеке Конгресса) таблицы Books (Книги) и // столбцом LOC таблицы BookCategories (Категории книг) ds->Relations->Add( // Отношения-> Добавить
"Book Category LOC->Book LOC Relation",
loc,
bloc);