Таблицы ADO.NET

Объект 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);
        }

Обновлено: 01.02.2019 — 09:45

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.