Объект DataTable:
DataTable — объект автономной части технологии ADO.NET, представляющий собой таблицу с данными.
Основными составляющими объекта DataTable являются объекты DataRow, представляющие собой строки таблицы с данными и объекты DataColumn, представляющие собой колонки таблицы.
Объекты DataRow содержаться в таблице в коллекции строк(DataRowCollection), а объекты DataColumn в коллекции столбцов таблицы(DataColumnCollection)
Объект DataColumn:
Объект DataColumn представляет собой отдельный столбец таблицы. При создании объекта DataColumn следует указать имя колонки и тип данных, которые будет содержать колонка.
Если не указать тип данных для колонки будет автоматически выбран тип String
После создания экземпляра DataColumn можно добавлять его в коллекцию столбцов экземпляра DataTable.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
static void Main(string[] args) { DataTable table = new DataTable("MyFirstTable"); DataColumn firstColumn = new DataColumn("First Column", typeof(int)); DataColumn secondColumn = new DataColumn("Second column", typeof(string)); DataColumnCollection columnCollection = table.Columns; columnCollection.AddRange(new DataColumn[]{firstColumn, secondColumn}); foreach (DataColumn column in table.Columns) Console.WriteLine("{0}: {1};", column.ColumnName, column.DataType); } |
Набор столбцов таблицы с их именами и типами данных называется схемой таблицы.
Объект DataRow:
Объект DataRow представляет собой отдельную строку таблицы.
Для создания объекта DataRow нельзя пользоваться конструктором. Строка может быть создана на основе схемы существующей таблицы.
Для создания строк у объекта DataTable есть метод NewRow(), возвращающий объект DataRow с полями, аналогичными столбцам таблицы.
1 |
DataRow newRow = table.NewRow(); |
При создании новой строки с помощью метода NewRow она не помещается в коллекцию строк таблицы.
Использование DataReader для создания схемы объекта DataTable:
На практике часто приходится создавать объекты DataTable с аналогичной схемой таблицы в источнике данных.
Объект DataReader предоставляет ряд методов для решения этой проблемы.
Метод GetName позволяет узнать имя столбца таблицы в источнике данных, а метод GetFieldType позволяет получить тип данных столбца таблицы в источнике данных
Следующий метод на основе переданного ему объекта SqlDataReader создает новый экземпляр DataTable со схемой, аналогичной таблице, к которой обращается DataReader.
1 2 3 4 5 6 7 8 9 |
private static DataTable CreateSchemaFromReader(SqlDataReader reader, string tableName) { DataTable table = new DataTable(tableName); for (int i = 0; i < reader.FieldCount; i++) table.Columns.Add(new DataColumn(reader.GetName(i), reader.GetFieldType(i))); return table; } |
Проверка данных:
Как правило таблицы, находящиеся в базе данных имеют ряд ограничений для данных, которые можно хранить в этих таблицах. Например некоторые столбцы могут хранить только уникальные данные, некоторые заполняются автоматически, а некоторые не могут хранить пустые значения.
Для создания таких ограничений в автономной части ADO.NET объекты DataTable и DataColumn имеют ряд свойств.
Свойства объекта DataColumn:
Для проверки данных на уровне таблиц объект DataColumnпредоставляет следующие свойства :
- Readonly – возвращает или задает значение, указывающее на допустимость изменения столбца после добавления строки в таблицу.
- AllowDBNull – возвращает или задает значение, указывающее на допустимость нулевых значений в этом столбце для строк, принадлежащих таблице.
- MaxLength – возвращает или задает максимальную длину текстового
- столбца.
- Unique — возвращает или задает значение, показывающее, должны ли
- значения в каждой строке столбца быть уникальными.
Ограничения DataTable:
Для проверки данных на уровне DataSet объект DataTable предоставляет коллекцию ConstraintCollection, которая может одержать экземпляры классов, наследуемых от базового класса Constraint. Обратиться к коллекции ConstraintCollection таблицы можно с помощью свойства Constraints.:
Для объекта DataTable можно задать следующие ограничения:
- UniqueConstraint — предоставляет ограничение на набор столбцов, в которых все значения должны быть уникальными. Следует пользоваться этим ограничением в том случае, когда необходимо гарантировать уникальность комбинаций значений различных полей таблицы
- PrimaryKey – особый вид ограничения на уникальность. Первичный ключ таблицы может быть только один
- ForeignKeyConstraint – ограничение, гарантирующее что нельзя создать строку в дочерней таблице, которая ссылается на несуществующую строку родительской таблицы.
Примеры:
Использование метода GetSchemaTable для получения информации о схеме таблицы к которой обращается объект DataReader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
static void Main(string[] args) { string conStr = @"Data Source=.\SQLEXPRESS; Initial Catalog=ShopDB; Integrated Security=True;"; // создание строки подключения SqlConnection connection = new SqlConnection(conStr); connection.Open(); SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", connection); SqlDataReader reader = cmd.ExecuteReader(); DataTable schemaTable = reader.GetSchemaTable(); //получение информации о схеме таблицы Customers foreach (DataRow row in schemaTable.Rows) // вывод на экран информации, предоставляемой методом GetSchemaTable { foreach (DataColumn column in schemaTable.Columns) Console.WriteLine("{0}: {1}", column.ColumnName, row[column]); Console.WriteLine(); } DataTable customers = new DataTable("Customers"); foreach (DataRow row in schemaTable.Rows) { var dataColumnToInsert = new DataColumn((string)row["ColumnName"], (Type)row["DataType"]); customers.Columns.Add(dataColumnToInsert); // добавление столбцов в таблицу customers } Console.WriteLine(new string('-', 20)); foreach (DataColumn customersColumn in customers.Columns) Console.WriteLine("{0}: {1}", customersColumn.ColumnName, customersColumn.DataType); // вывод имен и типов данных столбцов таблицы Customers reader.Close(); connection.Close(); Console.ReadKey(); } |
Свойство Reaonly объекта DataColumn позволяет задать значение, указывающее на допустимость изменения столбца после добавления строки в таблицу.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
static void Main(string[] args) { DataTable table = new DataTable(); DataColumn column = table.Columns.Add("ReadonlyColumn", typeof(string)); column.ReadOnly = true; // столбец таблицы c именем ReadonlyColumn доступен только для чтения DataRow newRow = table.NewRow(); newRow[0] = "ReadonlyValue"; table.Rows.Add(newRow); Console.WriteLine(table.Rows[0][0]); table.Rows[0][0] = "NewValue"; // ОШИБКА времени выполнения } |
Свойство AllowDBNull объекта DataColumn возвращает или задает значение, указывающее на допустимость нулевых значений в этом столбце для строк, принадлежащих таблице.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
static void Main(string[] args) { DataTable table = new DataTable(); DataColumn column = table.Columns.Add("AllowDBNullColumn", typeof(int)); column.AllowDBNull = false; DataRow newRow = table.NewRow(); newRow[0] = DBNull.Value; table.Rows.Add(newRow); //ошибка времени выполнения Console.WriteLine(table.Rows[0][0]); } |
Свойство MaxLength объекта DataColumn возвращает или задает максимальную длину текстового столбца.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
static void Main(string[] args) { DataTable table = new DataTable(); DataColumn column = table.Columns.Add("MaxLengthConstraintColumn", typeof(string)); column.MaxLength = 5; DataRow newRow = table.NewRow(); newRow[0] = "Some value"; table.Rows.Add(newRow); // ошибка времени выполнения Console.WriteLine(table.Rows[0][0]); } |
Свойство Unique объекта DataColumn возвращает или задает значение, показывающее, должны ли значения в каждой строке столбца быть уникальными.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
static void Main(string[] args) { DataTable table = new DataTable(); DataColumn column = table.Columns.Add("UniqueColumn", typeof(string)); column.Unique = true; DataRow newRow = table.NewRow(); newRow[0] = "NonUniqueValue"; table.Rows.Add(newRow); newRow = table.NewRow(); newRow[0] = "NonUniqueValue"; table.Rows.Add(newRow); // ошибка времени выполнения при нарушении ограничения Unique Console.WriteLine(table.Rows[0][0]); Console.WriteLine(table.Rows[1][0]); } |
Класс UniqueConstraint предоставляет ограничение на набор столбцов, в которых все значения должны быть уникальными.
Следует пользоваться этим ограничением в том случае, когда необходимо гарантировать уникальность комбинаций значений различных полей таблицы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
static class TableExtentions { public static void AddRow(this DataTable table, string column1Val, string column2Val) { var newRow = table.NewRow(); newRow[0] = column1Val; newRow[1] = column2Val; table.Rows.Add(newRow); } } class Program { static void Main(string[] args) { DataTable table = new DataTable(); DataColumn column1 = table.Columns.Add("Column1", typeof(string)); DataColumn column2 = table.Columns.Add("Column2", typeof(string)); table.Constraints.Add("tableUniqueConstraint", new[] { column1, column2 }, false); table.AddRow("Unique", "Unique"); table.AddRow("Unique", "Unique"); } } |
PrimaryKey – особый вид ограничения на уникальность. Первичный ключ таблицы может быть только один.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
static void Main(string[] args) { DataTable table = new DataTable(); DataColumn column1 = table.Columns.Add("Column1", typeof(string)); DataColumn column2 = table.Columns.Add("Column2", typeof(string)); table.Constraints.Add(new UniqueConstraint(column1, false)); Console.WriteLine("is unique: " + table.Columns[0].Unique); Console.WriteLine("Primary key columns count: "+ table.PrimaryKey.Length); if (table.PrimaryKey.Length != 0) Console.WriteLine("Primary key column name: " + table.PrimaryKey[0].ColumnName); else Console.WriteLine("Primary key column name: No data"); } |
ForeignKeyConstraint – ограничение, гарантирующее что нельзя создать строку в дочерней таблице, которая ссылается на несуществующую строку родительской таблицы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
static void Main(string[] args) { DataSet ds = new DataSet(); // создание DataSet DataTable parentTable = new DataTable(); // родительская таблица DataTable childTable = new DataTable(); // дочерняя таблица DataColumn childColumn = childTable.Columns.Add("ChildColumn", typeof(int)); DataColumn parentColumn = parentTable.Columns.Add("ParentColumn", typeof(int)); // ограничение ForeignKeyConstraint будет работать если родительская и дочерняя таблица находятся в одном объекте DataSet ds.Tables.AddRange(new DataTable[] { childTable, parentTable }); parentTable.Constraints.Add(new UniqueConstraint(parentColumn)); childTable.Constraints.Add(new ForeignKeyConstraint(parentColumn, childColumn)); DataRow parentRow = parentTable.NewRow(); parentRow[0] = 1; parentTable.Rows.Add(parentRow); DataRow childRow = childTable.NewRow(); childRow[0] = 1; // после создания ограничения ForeignKeyConstraint нельзя добавлять в дочернюю таблицу строку, ссылающиеся на несуществующие строки из родительской таблицы childRow[0] = 0; childTable.Rows.Add(childRow); } |