DataRow
30Работа с базами данных в .NET Framework --- ADO.NET --- DataRow
Мы видели, что коллекция объектов DataColumn представляет схему объекта DataTable. А коллекция объектов DataRow представляет конкретные данные в таблице. И если на складе имеются 20 автомобилей, то для хранения информации о них нужно 20 объектов DataRow. Некоторые (но не все) члены класса DataRow перечислены ниже:
- HasErrors, GetColumnsInError(), GetColumnError(), ClearErrors(), RowError
Свойство HasErrors возвращает логическое значение, означающее наличие ошибок. Если они есть, то метод GetColumnsInError() позволяет получить ошибочные столбцы, а метод GetColumnError() — получить описание ошибки. Аналогично, метод ClearErrors() удаляет из строки всю информацию об ошибках. Свойство RowError позволяет создать текстовое описание ошибки для данной строки
- ItemArray
Свойство, задающее или получающее все значения столбцов строки в виде массива объектов
- RowState
Свойство, позволяющее зафиксировать текущее состояние объекта DataRow в содержащем его DataTable с помощью значений перечисления RowState (новый, измененный, не измененный или удаленный)
- Table
Свойство, позволяющее получить ссылку на объект DataTable, содержащий данный объект DataRow
- AcceptChanges(), RejectChanges()
Методы для фиксации или отмены всех изменений, выполненных в данной строке с момента последнего вызова AcceptChanges()
- BeginEdit(), EndEdit(), CancelEdit()
Методы, начинающие, заканчивающие или отменяющие операцию редактирования для объекта DataRow
- Delete()
Метод, помечающий данную строку для удаления при вызове метода AcceptChanges()
- IsNull()
Метод, получающий значение, которое указывает, содержит ли заданный столбец пустое значение
Работа с объектами DataRow несколько отличается от работы с DataColumn: невозможно напрямую создать экземпляр данного типа, т.к. у него нет общедоступного конструктора:
// Ошибка! Нет общедоступного конструктора!
DataRow dr = new DataRow();
Вместо этого новый объект DataRow можно получить из конкретного DataTable. Предположим, например, что в таблицу Inventory нужно вставить две строки. Метод DataTable.NewRow() позволяет получить очередное место в таблице, после чего можно заполнить каждый столбец с помощью индексатора типа. При этом можно указать либо строковое имя, присвоенное объекту DataColumn, либо номер его позиции (начиная с нуля):
// Добавление строк в таблицу Inventory
DataRow carRow = inventoryTable.NewRow();
carRow["Make"] = "BMW";
carRow["Color"] = "Black";
carRow["PetName"] = "Hamlet";
inventoryTable.Rows.Add(carRow);
carRow = inventoryTable.NewRow();
carRow[1] = "Saab";
carRow[2] = "Red";
carRow[3] = "Sea Breeze";
inventoryTable.Rows.Add(carRow);
Если передать методу индексатора типа DataRow неверное имя столбца или позицию, будет сгенерировано исключение времени выполнения.
Теперь у вас есть один объект DataTable, содержащий две строки. Конечно, этот общий процесс можно повторить, чтобы создать ряд объектов DataTable, определить их схемы и заполнить данными. Но прежде чем вставить объект inventoryTable в объект DataSet, необходимо разобраться с очень важным свойством RowState.
Свойство RowState
Свойство RowState применяется для программной идентификации множества всех строк таблицы, которые изменили свое первоначальное значение, были вставлены и т.п. Это свойство может принимать любое значение из перечисления DataRowState:
Значение | Назначение |
---|---|
Added | Строка была добавлена в DataRowCollection, a AcceptChanges() еще не был вызван |
Deleted | Строка была помечена для удаления с помощью метода Delete() класса DataRow, a AcceptChanges() еще не был вызван |
Detached | Строка была создана, но не включена ни в какой DataRowCollection. Объект DataRow находится в этом состоянии после его создания, но до занесения в какую-либо коллекцию, либо после исключения из коллекции |
Modified | Строка была изменена, a AcceptChanges() еще не был вызван |
Unchanged | Строка не была изменена после последнего вызова AcceptChanges() |
При программной работе со строками объекта DataTable значения в свойство RowState заносятся автоматически. Объект ADO.NET DataRow вполне разумно отслеживает свое состояние. Поэтому владеющий этим объектом объект DataTable может определить добавленные, измененные или удаленные строки. Это очень важная возможность DataSet, потому что когда наступит время послать информацию в хранилище данных, будут отправлены только измененные данные.
Свойство DataRowVersion
Кроме отслеживания текущего состояния строк с помощью свойства RowState, объект DataRow отслеживает три возможные версии содержащихся в нем данных с помощью свойства DataRowVersion. При первоначальном создании объект DataRow содержит лишь одну копию данных, которая считается "текущей версией". Но при программной работе с объектом DataRow (с помощью вызовов различных методов) появляются дополнительные версии данных. Конкретнее, свойство DataRowVersion может содержать любое значение соответствующего перечисления DataRowVersion:
Значение | Назначение |
---|---|
Current | Представляет текущее значение строки, даже после выполнения изменений |
Default | Стандартный вариант DataRowState. Если значение DataRowState равно Added, Modified или Deleted, то стандартной версией является Current. Для значения DataRowState, равного Detached, стандартной версией является Proposed |
Original | Представляет значение, первоначально вставленное в DataRow, или значение при последнем вызове AcceptChanges() |
Proposed | Значение строки, редактируемой в настоящий момент с помощью вызова BeginEdit() |
Как показано в таблице, значение свойства DataRowVersion в большинстве случаев зависит от значения свойства DataRowState. А как было сказано ранее, значение свойства DataRowState автоматически изменяется при вызовах различных методов объекта DataRow (а в некоторых случаях DataTable). Ниже представлена схема влияния этих методов на значение свойства DataRowVersion произвольной строки:
При изменении значения строки, после вызова метода DataRow.BeginEdit(), становятся доступны значения Current и Proposed.
При вызове метода DataRow.CancelEdit() значение Proposed удаляется.
После вызова DataRow.EndEdit() значение Proposed меняется на Current.
После вызова метода DataRow.AcceptChanges() значение Original становится равным значению Current. То же самое происходит и при вызове DataTable.AcceptChanges().
После вызова DataRow.RejectChanges() значение Proposed отбрасывается, и версия становится равной Current.
Да, все это несколько запутанно — особенно из-за того, что в любой данный момент времени DataRow может иметь, а может и не иметь все версии (при попытке получения версии строки, которая в данный момент не отслеживается, возникнут исключения времени выполнения). Но поскольку DataRow отслеживает три копии данных, то, несмотря на эту сложность, можно без особого труда создать пользовательский интерфейс, который позволяет конечному пользователю изменить значения, потом передумать и отказаться от этих изменений или зафиксировать их, чтобы они хранились постоянно.