DataSet и DataTable

Данное руководство устарело. Актуальное руководство: по ADO.NET и работе с базами данных в .NET 6

Последнее обновление: 31.10.2015

После получения данных из базы данных через SqlDataAdapter в DataSet мы можем локально работать с этими данными вне зависимости от наличия подключения. Более того если нам даже и не надо использовать никакую базу данных, но при этом мы хотим иметь удобный функционал для работы с данными в виде наборов таблиц, то мы также можем воспользоваться классом DataSet.

Объект DataSet содержит таблицы, которые представлены типом DataTable. Таблица, в свою очередь, состоит из столбцов и строк. Каждый столбец представляет объект DataColumn, а строка - объект DataRow. Все данные строки хранятся в свойстве ItemArray, который представляет массив объектов - значений отдельных ячеек строки. Например, получим все таблицы и выведем их содержимое:

static void Main(string[] args) 
{
	string sql = "SELECT * FROM Users";
	string connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=usersdb;Integrated Security=True";
	using (SqlConnection connection = new SqlConnection(connectionString))
	{
		connection.Open();
        SqlDataAdapter adapter = new SqlDataAdapter(sql, connection);

        DataSet ds = new DataSet();
        adapter.Fill(ds);
        // перебор всех таблиц
        foreach (DataTable dt in ds.Tables)
        {
            Console.WriteLine(dt.TableName); // название таблицы
            // перебор всех столбцов
            foreach(DataColumn column in dt.Columns)
                Console.Write("\t{0}", column.ColumnName);
            Console.WriteLine();
            // перебор всех строк таблицы
            foreach (DataRow row in dt.Rows)
            {
                // получаем все ячейки строки
                var cells = row.ItemArray;
                foreach (object cell in cells)
                    Console.Write("\t{0}", cell);
                Console.WriteLine();
            }
        }
	}
}
DataSet и DataTable в ADO.NET

Теперь рассмотрим, как мы можем работать с объектами DataSet и DataTable без какой-либо базы данных. Например, создадим вручную в DataSet несколько таблиц и определим их структуру:

static void Main(string[] args)
{
    DataSet bookStore = new DataSet("BookStore");
    DataTable booksTable = new DataTable("Books");
    // добавляем таблицу в dataset
    bookStore.Tables.Add(booksTable);

    // создаем столбцы для таблицы Books
    DataColumn idColumn = new DataColumn("Id", Type.GetType("System.Int32"));
    idColumn.Unique = true; // столбец будет иметь уникальное значение
    idColumn.AllowDBNull = false; // не может принимать null
	idColumn.AutoIncrement = true; // будет автоинкрементироваться
    idColumn.AutoIncrementSeed = 1; // начальное значение
    idColumn.AutoIncrementStep = 1; // приращении при добавлении новой строки

    DataColumn nameColumn = new DataColumn("Name", Type.GetType("System.String"));
    DataColumn priceColumn = new DataColumn("Price", Type.GetType("System.Decimal"));
    priceColumn.DefaultValue = 100; // значение по умолчанию
    DataColumn discountColumn = new DataColumn("Discount", Type.GetType("System.Decimal"));
    discountColumn.Expression = "Price * 0.2";

    booksTable.Columns.Add(idColumn);
    booksTable.Columns.Add(nameColumn);
    booksTable.Columns.Add(priceColumn);
    booksTable.Columns.Add(discountColumn);
    // определяем первичный ключ таблицы books
    booksTable.PrimaryKey = new DataColumn[] { booksTable.Columns["Id"] };

    DataRow row = booksTable.NewRow();
    row.ItemArray = new object[] { null, "Война и мир", 200 };
    booksTable.Rows.Add(row); // добавляем первую строку
    booksTable.Rows.Add(new object[] { null, "Отцы и дети", 170 }); // добавляем вторую строку

    Console.Write("\tИд \tНазвание \tЦена \tСкидка");
    Console.WriteLine();
    foreach (DataRow r in booksTable.Rows)
    {
        foreach (var cell in r.ItemArray)
            Console.Write("\t{0}", cell);
        Console.WriteLine();
    }
    Console.Read();       
}
DataTable в ADO.NET

Разберем весь код. Сначала создаются объекты DataSet и DataTable, в конструктор которых передается название. Затем создается четыре столбца. Каждый столбец в конструкторе принимает два параметра: имя столбца и его тип.

DataColumn idColumn = new DataColumn("Id", Type.GetType("System.Int32"));

Причем для столбца Id устанавливается, что значения этого столбца должны иметь уникальное значение, не должны принимать null, и их значение при добавлении нового объекта будет инкрементироваться на единицу. То есть фактически это стандартный столбец Id, как в большинстве баз данных.

Далее создается еще три столбца, при этом для столбца Discount устанавливается свойство Expression, указывающее на выражение, которое будет использоваться для вычисления значения столбца:

discountColumn.Expression = "Price * 0.2";

То есть в данном случае значение столбца Discount равно значению столбца Price, помноженного на 0.2.

Затем устанавливается первичный ключ для таблицы с помощью свойства PrimaryKey:

booksTable.PrimaryKey = new DataColumn[] { booksTable.Columns["Id"] };

В роли первичного ключа выступает столбец Id. Но мы также можем использовать набор различных столбцов для создания составного ключа.

После определения схемы таблицы в нее добавляются две строки:

DataRow row = booksTable.NewRow();
row.ItemArray = new object[] { null, "Война и мир", 200 };
booksTable.Rows.Add(row); // добавляем первую строку
booksTable.Rows.Add(new object[] {null, "Отцы и дети", 170 });

Значения в метод booksTable.Rows.Add можно передать как напрямую в виде массива объектов, так и в виде объекта DataRow. При этом нам надо передать ровно столько значений, сколько в таблице столбцов. Однако поскольку первый столбец Id устанавливается через автоинкремент, мы можем передать значение null - оно все равно будет игнорироваться. Также мы можем опустить последний параметр для столбца Discount, так как его значение вычисляется с помощью выражения "Price * 0.2". Более того мы даже можем опустить значение для третьего столбца Price, так как у него установлено свойство DefaultValue, которое устанавливает значение по умолчанию, если значение отсутствует:

booksTable.Rows.Add(new object[] {null, "Отцы и дети"});

И в конце идет перебор строк таблицы.

Кроме добавления мы можем производить и другие операции со строками. Например, мы можем получить строку по индексу:

DataRow row = booksTable.Rows[0]; // первая строка

Получив строку по индексу, можно изменить ее ячейки:

booksTable.Rows[0][2] = 300; //третьей ячейке первой строки присваивается значение 300

И также можно удалять строку:

booksTable.Rows.RemoveAt(1); // удаление второй строки по индексу
// другой сопосб удаления
DataRow row = booksTable.Rows[0];
booksTable.Rows.Remove(row);

Используя метод Select() объекта DataTable мы легко можем найти строки, которые соответствуют определенному критерию. Например, получим строки, в которых цена больше 120:

var selectedBooks = booksTable.Select("Price > 120");
foreach (var b in selectedBooks)
    Console.WriteLine("{0} - {1}", b["Name"], b["Price"]);
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850