Довольно часто некоторые поля данных надо скрыть, не отображать их на форме (например, поля первичных автоинкрементируемых ключей). Для этого просто не включайте эти поля в множество колонок (объектов DataGridViewTextBoxColumn), которое добавляется в DataGridView (studsGrid.Columns.Add(tb);).
Класс DataSet значительно упрощает операции записи и чтения данных. Он имеет множество встроенных свойств и методов, поддерживающих управление данными в формате XML. Начнем с метода записи данных.
void Save(string file)
{
if (file == null || ds.Tables[0].Rows.Count == 0)
return;
ds.WriteXml(file);
fileName = file;
}
Имя файла получим от пользователя с помощью метода FileDlg.
string FileDlg(bool bOpen)
{
FileDialog dlg = bOpen ? (FileDialog)new OpenFileDialog()
: (FileDialog)new SaveFileDialog();
dlg.InitialDirectory = Application.StartupPath + "\\..\\..";
dlg.Filter = "People files (*.xml)|*.xml";
dlg.Title = "Select data file to " + (bOpen ? "open" : "save");
dlg.FileName = fileName;
return dlg.ShowDialog() == DialogResult.OK ? dlg.FileName : null;
}
Чтение всего набора данных из XML-файла выполним в методе Open. Для обеспечения видимости новых классов попросите студию вставить недостающие директивы using.
void Open(string file)
{
if (file == null)
return;
ds.Clear();
ds.ReadXml(file);
fileName = file;
Text = "Students Table: " + file.Substring(file.LastIndexOf('\\') + 1);
}
Отметьте, что при чтении набора данных (DataSet) из файла он рождается заново, поэтому старые данные необходимо уничтожить (см. вызов метода Clear). Запустите приложение и сохраните данные в произвольном файле папки проекта. Теперь можно закомментировать строку вызова InitTables и проверить поведение приложения при начальном открытии файла с данными.
Связь (relationship) между первой таблицей Studs и второй — Exams имеет вид один ко многим. В реальной базе данных это, как вы знаете, означает, что первичные ключи первой таблицы неоднократно скопированы во вторую и эти копии носят имя связанных ключей (foreign keys). Они ссылаются на строки главной, первичной таблицы, образуя ссылочную целостность данных (referential integrity: каждый экзамен принадлежит какому-то студенту).
Для того, чтобы создать подобную структуру связей в DataSet, необходимо (кроме двух объектов DataTable) добавить объект класса DataRelation. Ссылка на этот объект помещается и хранится в коллекции Relations объекта DataSet. При создании DataRelation надо указать связываемые колонки и задать имя связи. Имя играет решающую роль в настройке механизма DataBinding (так же, как и имена синхронизируемых свойств).
Следующий фрагмент надо добавить в метод InitDataSet (после кода, который помещает таблицы в DataSet).
DataRelation dr = new DataRelation("StudExam",
studs.Columns["ID"], exams.Columns["StudID"]);
ds.Relations.Add(dr);
Здесь мы создаем объект класса DataRelation и помещаем его в коллекцию Relations объекта DataSet. Этого кода достаточно для синхронизации отображения данных связанных таблиц. Суть синхронизации в том, что мы показываем не все экзамены, а только экзамены студента, активного (выбранного) в первой таблице. С этой задачей справится механизм DataBinding, которому надо дать ссылку на DataRelation.
Но если мы хотим не только просматривать данные, но и вносить изменения, то для сохранения целостности по ссылкам, необходимо добавить код, создающий объект класса ForeignKeyConstraint. Он задает ограничение, накладываемое на данные обеих таблиц. Ограничение (constraint) типа FK-PK (ForeignKey-PrimaryKey) следит за тем, чтобы не нарушалась целостность данных по ссылкам.
Ограничения, в отличие от связей, попадают в коллекцию ограничений таблицы, а не в DataSet. Каждый объект класса DataTable имеет список ограничений, накладываемых на ее столбцы. Имея представление о том, как устроена библиотека классов .NET Framework, нетрудно догадаться, что этот список представляет собой коллекцию объектов какого-то специального класса.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.