Объект DataTable:
DataTable — объект автономной части технологии ADO.NET, представляющий собой таблицу с данными.
Основными составляющими объекта DataTable являются объекты DataRow, представляющие собой строки таблицы с данными и объекты DataColumn, представляющие собой колонки таблицы.
Объекты DataRow содержаться в таблице в коллекции строк(DataRowCollection), а объекты DataColumn в коллекции столбцов таблицы(DataColumnCollection)
Объект DataColumn:
Объект DataColumn представляет собой отдельный столбец таблицы. При создании объекта DataColumn следует указать имя колонки и тип данных, которые будет содержать колонка.
Если не указать тип данных для колонки будет автоматически выбран тип String
После создания экземпляра DataColumn можно добавлять его в коллекцию столбцов экземпляра DataTable.
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 с полями, аналогичными столбцам таблицы.
DataRow newRow = table.NewRow();
При создании новой строки с помощью метода NewRow она не помещается в коллекцию строк таблицы.
Использование DataReader для создания схемы объекта DataTable:
На практике часто приходится создавать объекты DataTable с аналогичной схемой таблицы в источнике данных.
Объект DataReader предоставляет ряд методов для решения этой проблемы.
Метод GetName позволяет узнать имя столбца таблицы в источнике данных, а метод GetFieldType позволяет получить тип данных столбца таблицы в источнике данных
Следующий метод на основе переданного ему объекта SqlDataReader создает новый экземпляр DataTable со схемой, аналогичной таблице, к которой обращается DataReader.
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
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 позволяет задать значение, указывающее на допустимость изменения столбца после добавления строки в таблицу.
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 возвращает или задает значение, указывающее на допустимость нулевых значений в этом столбце для строк, принадлежащих таблице.
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 возвращает или задает максимальную длину текстового столбца.
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 возвращает или задает значение, показывающее, должны ли значения в каждой строке столбца быть уникальными.
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 предоставляет ограничение на набор столбцов, в которых все значения должны быть уникальными.
Следует пользоваться этим ограничением в том случае, когда необходимо гарантировать уникальность комбинаций значений различных полей таблицы.
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 – особый вид ограничения на уникальность. Первичный ключ таблицы может быть только один.
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 – ограничение, гарантирующее что нельзя создать строку в дочерней таблице, которая ссылается на несуществующую строку родительской таблицы.
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);
}