Опубликован: 07.05.2010 | Доступ: свободный | Студентов: 1678 / 62 | Оценка: 4.56 / 4.06 | Длительность: 34:11:00
Лекция 12:

Компоненты данных ADO.NET

Фильтрация извлеченных автономных данных с помощью DataView

Объект DataView можно использовать для фильтрации извлеченных автономных данных перед их отображением пользователю. Для этого нужно задать объекту значение свойства RowFilter, которое использует те же операторы логических условий, что и в SQL-запросе. В таблице приведены наиболее часто используемые операторы фильтрации

Некоторые операторы фильтрации в свойстве DataView.RowFilter
Операция Описание
<, >, <=, >= Сравнение числовых или строковых типов
<>, = Проверка на эквивалентность
NOT Отрицание
BETWEEN Указывает диапазон включительно. Например, Units BETWEEN 5 AND 15 выбирает строки, у которых значение столбца Units находится в диапазоне 5-15 включительно
IS NULL Проверяет столбец на нулевое значение
IN(a, b, c) Краткая форма операции OR с одним и тем же полем. Проверяет эквивалентность значения столбца любому из перечисленных значений списка нужной длины, например a, b, c
LIKE Проверяет соответствие строкового значения шаблону
+ Конкатенация складывает два числа или склеивает две строки
- Вычитает одно числовое значение из другого
* Перемножает два числовых значения
/ Делит одно числовое значение на другое
% Вычисляет модуль - остаток от деления одного числового значения на другое
AND Логическое умножение
OR Логическое сложение

Приведем пример страницы, в которой имеются три элемента GridView. Каждый из них привязан через DataView к одним и тем же данным DataTable, но с разными установками фильтрации.

  • Создайте копию страницы GridViewDataView.aspx с именем DataViewFiltered.aspx и назначьте ее стартовой
  • В странице DataViewFiltered.aspx выполните следующие изменения
    • В директиве @Page установите новое значение атрибута Inherits="DataViewFiltered"
    • Поменяйте HTML-дескрипторы <h2> на <h3> со следующим содержимым
      • <h3>
        Фильтровать продукт Chocolade<br />
        (RowFilter = "ProductName = 'Chocolade'")
        </h3>
      • <h3>
        Фильтровать продукты, которых нет в заказах и на складе<br />
        (RowFilter = "UnitsInStock = 0 AND UnitsOnOrder = 0")
        </h3>
      • <h3>
        Фильтровать продукты, чье название начинается с буквы P<br />
        (RowFilter = "ProductName LIKE 'P%'")
        </h3>
  • В файле поддержки DataViewFiltered.aspx.cs установите новое имя класса DataViewFiltered и наполните файл следующим кодом
    using System;
    using System.Data;
        
    using System.Web.Configuration;
    using System.Data.SqlClient;
        
    public partial class DataViewFiltered : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Содать Connection, DataAdapter и DataSet
            string connectionString = WebConfigurationManager.
                ConnectionStrings["Northwind"].ConnectionString;
            SqlConnection con = new SqlConnection(connectionString);
            string sql = 
                "SELECT ProductID, ProductName, UnitsInStock, UnitsOnOrder, "
              + "Discontinued FROM Products";
            SqlDataAdapter adapter = new SqlDataAdapter(sql, con);
            DataSet dataset = new DataSet();
            adapter.Fill(dataset, "ProductsTable");
        
            // Фильтровать продукт Chocolade
            DataView view1 = new DataView(dataset.Tables["ProductsTable"]);
            view1.RowFilter = "ProductName = 'Chocolade'";
            GridView1.DataSource = view1;
        
            // Фильтровать продукты, которых нет в заказах и на складе
            DataView view2 = new DataView(dataset.Tables["ProductsTable"]);
            view2.RowFilter = "UnitsInStock = 0 AND UnitsOnOrder = 0";
            GridView2.DataSource = view2;
        
            // Фильтровать продукты, чье название начинается с буквы P
            DataView view3 = new DataView(dataset.Tables["ProductsTable"]);
            view3.RowFilter = "ProductName LIKE 'P%'";
            GridView3.DataSource = view3;
        
            // Загрузить привязанные данные во все элементы отображения GridView
            this.DataBind();
        }
    }
  • Запустите страницу DataViewFiltered.aspx и получите следующий результат

Фильтровать продукт Chocolade (RowFilter = "ProductName = 'Chocolade'")

ProductID ProductName UnitsInStock UnitsOnOrder Discontinued
48 Chocolade 15 70

Фильтровать продукты, которых нет в заказах и на складе (RowFilter = "UnitsInStock = 0 AND UnitsOnOrder = 0")

ProductID ProductName UnitsInStock UnitsOnOrder Discontinued
5 Chef Anton's Gumbo Mix 0 0

17 Alice Mutton 0 0

29 Th№ringer Rostbratwurst 0 0

53 Perth Pasties 0 0

Фильтровать продукты, чье название начинается с буквы P (RowFilter = "ProductName LIKE 'P%'")

ProductID ProductName UnitsInStock UnitsOnOrder Discontinued
16 Pavlova 29 0

53 Perth Pasties 0 0

55 Pтtщ chinois 115 0

Класс System.Data.DataView также имеет свойство RowStateFilter, которое можно использовать для фильтрации данных так, чтобы отображались только строки, имеющие определенное состояние (вставленные, помеченные на удаление, модифицированные или неизмененные). По умолчанию это свойство установлено на отображение всех строк, кроме помеченных на удаление.

Фильтрация извлеченных автономных данных в DataView с установкой отношений

Класс DataView может выполнять и более сложную фильтрацию на основе таблиц, связанных отношением "Главный-подчиненный". Например, можно отобразить категории, каждая из которых содержит более 20 наименований продуктов, или отобразить заказчиков, сделавших определенное количество покупок.

Продемонстрируем эту возможность на примере двух таблиц: Categories и Products учебной базы Northwind.

  • Сделайте копию страницы DataSetRelationShips.aspx и назовите ее DataViewRelation.aspx
  • Исправьте значения атрибута Inherits в директиве @Page страницы и имя класса в файле поддержки
  • Удалите со страницы DataViewRelation.aspx текстовую метку lblInfo и поместите вместо нее заголовочный дескриптор
    <h2>Категории с продуктами дороже $50</h2>
  • Поместите после заголовочного дескриптора элемент управления GridView из вкладки Data панели Toolbox
  • Скорректируйте файл поддержки страницы DataViewRelation.aspx.cs следующим образом
    using System;
    using System.Data;
        
    using System.Web.Configuration;
    using System.Data.SqlClient;
    using System.Text;
        
    public partial class DataSetRelationShips : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Извлекаем строку соединения с именем Northwind из файла web.config
            string connectionString = WebConfigurationManager.
                ConnectionStrings["Northwind"].ConnectionString;
        
            // Создаем объект соединения
            SqlConnection con = new SqlConnection(connectionString);
        
            // Формируем строки SQL-запросов
            string sqlCategories = "SELECT CategoryID, CategoryName FROM Categories";
            string sqlProducts = "SELECT ProductName, CategoryID, UnitPrice FROM Products";
        
            // Создаем объект DataAdapter
            SqlDataAdapter adapter = new SqlDataAdapter(sqlCategories, con);
        
            // Создаем пустой объект DataSet набора данных
            DataSet dataset = new DataSet();
        
            // Выполняем два запроса к БД с открытием 
            // и закрытием соединения вручную.
            // Возможные исключения не обрабатываем, а просто подавляем
            try
            {
                con.Open();
                // Наполнить DataSet данными из таблицы Categories
                // с именованной меткой CatTable
                adapter.Fill(dataset, "CatTable");
                // Сменить команду и добавить в DataSet данные
                // с именованной меткой ProdTable из таблицы Products
                adapter.SelectCommand.CommandText = sqlProducts;
                adapter.Fill(dataset, "ProdTable");
            }
            finally
            {
                con.Close();
            }
        
            // Определение отношения между  извлеченными в DataSet
            // именованными данными CatTable и ProdTable
            DataRelation relation = new DataRelation(
                "CatProd",                                          // Имя отношения
                dataset.Tables["CatTable"].Columns["CategoryID"],   // Родительская таблица
                dataset.Tables["ProdTable"].Columns["CategoryID"]   // Дочерняя таблица
                                                        );
            // Добавление отношения в коллекцию отношений DataSet
            dataset.Relations.Add(relation);
        
            // Создаем объект DataView, в который загружаем данные CatTable
            DataView view1 = new DataView(dataset.Tables["CatTable"]);
        
            // Устанавливаем фильтр для отображения только категорий продуктов,
            // цена которых в связанной таблице продуктов удовлетворяет условию
            // "Самый дорогой продукт дороже 50"
            view1.RowFilter = "MAX(Child(CatProd).UnitPrice) > 50";
        
            // Показываем отфильтрованные данные пользователю
            GridView1.DataSource = view1;
            GridView1.DataBind();
        }
    }
  • Назначьте страницу DataViewRelation.aspx стартовой и выполните ее

Должен получиться следующий результат

Категории с продуктами дороже $50

CategoryID CategoryName
1 Beverages
3 Confections
4 Dairy Products
6 Meat/Poultry
7 Produce
8 Seafood

В фильтре мы установили условие, чтобы показать пользователю только те записи в родительской таблице, для которых в дочерней связанной таблице имеется хотя бы одна запись со значением поля UnitPrice>50. Это означает, что выводятся категории продуктов, в которых хотя бы один продукт дороже $50.

Добавление к автономным данным вычисляемых столбцов

Таким образом, класс DataSet позволяет одноразово загрузить нужные данные из источника, а затем в отсоединенном автономном режиме что-то с ними делать. До сих пор мы показывали пользователю все автономные данные, полученные по SQL-запросу. Показывали данные с наложением некоторых условий в методе

DataSet.Tables["TableName"].Select("Дополнительное_условие")

Показывали, также, данные с условием, наложенным в свойстве DataView.RowFilter вспомогательного объекта DataView.

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

Чтобы создать вычисляемый столбец в DataSet, необходимо отдельно создать новый объект класса DataColumn, установить формулу в его свойстве Expression и добавить этот столбец в коллекцию Columns объекта DataSet

dataset.Tables["TableName"].Columns.Add(datacolumn)

Рассмотрим пример, в котором создадим столбец, объединяющий фамилию и имя каждого служащего из таблицы Employees учебной базы данных Northwind.

  • Создайте копию файла TestDataSet.aspx с именем ExpressionColumns.aspx и назначьте ее стартовой
  • Откройте на редактирование файл поддержки ExpressionColumns.aspx.cs и отредактируйте его так
    using System;
    using System.Data;
        
    using System.Web.Configuration;
    using System.Data.SqlClient;
    using System.Text;
        
    public partial class ExpressionColumns : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Извлекаем строку соединения с именем Northwind из файла web.config
            string connectionString = WebConfigurationManager.
                ConnectionStrings["Northwind"].ConnectionString;
        
            // Формируем строку SQL для выборки всех данных таблицы Employees
            string commandString = "SELECT * FROM Employees";
        
            // Создаем и настраиваем экземпляр класса SqlDataAdapter
            SqlDataAdapter adapter = 
                new SqlDataAdapter(commandString, connectionString);
        
            // Создаем объект DataSet результирующего набора данных
            DataSet dataset = new DataSet();
        
            // Безопасно заполняем данными объект DataTable с произвольным 
            // именем, например "EmployeesResult", созданного объекта DataSet
            try
            {
                adapter.Fill(dataset, "EmployeesResult");
            }
            catch
            {
                throw new ApplicationException("Ошибка данныx.");
            }
        
            // Создаем именованный столбец и добавляем к таблице в DataSet
            string strExpr = 
                "'Сотрудник ' + TitleOfCourtesy + ' ' + LastName + ', ' + FirstName";
            DataColumn column = new DataColumn("FullName", typeof(string), strExpr);
            dataset.Tables["EmployeesResult"].Columns.Add(column);
        
            // Перебираем все объекты DataRow с полученным записами
            StringBuilder htmlStr = new StringBuilder("");
            foreach (DataRow dr in dataset.Tables["EmployeesResult"].Rows)
            {
                htmlStr.Append("<li>");
                // Существующий столбец
                htmlStr.Append(dr["EmployeeID"].ToString() + ") ");
                htmlStr.Append("<b>");
                // Новый столбец
                htmlStr.Append(dr["FullName"].ToString());  
                htmlStr.Append("</b>");
                htmlStr.Append("</li>");
            }
        
            // Отображаем полученные данные
            lblInfo.Text = "<h2>Список сотрудников</h2>";
            lblInfo.Text += htmlStr.ToString();
        }
    }
  • Выполните страницу ExpressionColumns.aspx и получите следующий результат

Список сотрудников

  • 1) Сотрудник Ms. Davolio, Nancy
  • 2) Сотрудник Dr. Fuller, Andrew
  • 3) Сотрудник Ms. Leverling, Janet
  • 4) Сотрудник Mrs. Peacock, Margaret
  • 5) Сотрудник Mr. Buchanan, Steven
  • 6) Сотрудник Mr. Suyama, Michael
  • 7) Сотрудник Mr. King, Robert
  • 8) Сотрудник Ms. Callahan, Laura
  • 9) Сотрудник Ms. Dodsworth, Anne

Добавление к автономным данным вычисляемых столбцов для связанных таблиц

Можно создать в DataSet вычисляемые столбцы для связанных строк. Например, можно добавить в виртуальную таблицу CatTable столбец, показывающий количество связанных строк виртуальной таблицы ProdTable. В этом случае нужно определить отношение объектом DataRelation и использовать агрегатную функцию SQL, такую, как AVG(), MAX(), MIN(), COUNT().

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

  • Создайте копию страницы DataViewRelation.aspx с именем ExpressionColumnsRelation.aspx и назначьте ее стартовой
  • Исправьте значения атрибута Inherits в директиве @Page страницы и имя класса в файле поддержки
  • Измените на странице заголовочный дескриптор на
    <h2>Добавление вычисляемых столбцов</h2>
  • Откройте кодовый файл ExpressionColumnsRelation.aspx.cs на редактирование и откорректируйте его так
    using System;
    using System.Data;
        
    using System.Web.Configuration;
    using System.Data.SqlClient;
    using System.Text;
        
    public partial class ExpressionColumnsRelation : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Извлекаем строку соединения с именем Northwind из файла web.config
            string connectionString = WebConfigurationManager.
                ConnectionStrings["Northwind"].ConnectionString;
        
            // Создаем объект соединения
            SqlConnection con = new SqlConnection(connectionString);
        
            // Формируем строки SQL-запросов
            string sqlCategories = "SELECT CategoryID, CategoryName FROM Categories";
            string sqlProducts = "SELECT ProductName, CategoryID, UnitPrice FROM Products";
        
            // Создаем объект DataAdapter
            SqlDataAdapter adapter = new SqlDataAdapter(sqlCategories, con);
        
            // Создаем пустой объект DataSet набора данных
            DataSet dataset = new DataSet();
        
            // Выполняем два запроса к БД с открытием 
            // и закрытием соединения вручную.
            // Возможные исключения не обрабатываем, а просто подавляем
            try
            {
                con.Open();
                // Наполнить DataSet данными из таблицы Categories
                // с именованной меткой CatTable
                adapter.Fill(dataset, "CatTable");
                // Сменить команду и добавить в DataSet данные
                // с именованной меткой ProdTable из таблицы Products
                adapter.SelectCommand.CommandText = sqlProducts;
                adapter.Fill(dataset, "ProdTable");
            }
            finally
            {
                con.Close();
            }
        
            // Определение отношения между  извлеченными в DataSet
            // именованными данными CatTable и ProdTable
            DataRelation relation = new DataRelation(
                "CatProd",                                          // Имя отношения
                dataset.Tables["CatTable"].Columns["CategoryID"],   // Родительская таблица
                dataset.Tables["ProdTable"].Columns["CategoryID"]   // Дочерняя таблица
                                                        );
            // Добавление отношения в коллекцию отношений DataSet
            dataset.Relations.Add(relation);
        
            // Создать вычисляемые столбцы и добавить их в DataSet
            DataColumn count = new DataColumn("Кол. продуктов", typeof(int), 
                "COUNT(Child(CatProd).CategoryID)");
            dataset.Tables["CatTable"].Columns.Add(count);
            DataColumn max = new DataColumn("Самый дорогой продукт", typeof(decimal),
                "MAX(Child(CatProd).UnitPrice)");
            dataset.Tables["CatTable"].Columns.Add(max);
            DataColumn min = new DataColumn("Самый дешевый продукт", typeof(decimal),
                "MIN(Child(CatProd).UnitPrice)");
            dataset.Tables["CatTable"].Columns.Add(min);
        
            // Меняем названия заголовков столбцов на русский язык
            dataset.Tables["CatTable"].Columns["CategoryID"].ColumnName = "№ п/п";
            dataset.Tables["CatTable"].Columns["CategoryName"].ColumnName = "Наименование категории";
        
            // Показываем данные пользователю
            GridView1.DataSource = dataset.Tables["CatTable"];
            GridView1.DataBind();
        }
    }
  • Исполните страницу ExpressionColumnsRelation.aspx и получите следующий результат

Добавление вычисляемых столбцов

№ п/п Наименование категории Кол. продуктов Самый дорогой продукт Самый дешевый продукт
1 Beverages 12 263,5000 4,5000
2 Condiments 12 43,9000 10,0000
3 Confections 13 81,0000 9,2000
4 Dairy Products 10 55,0000 2,5000
5 Grains/Cereals 7 38,0000 7,0000
6 Meat/Poultry 6 123,7900 7,4500
7 Produce 5 53,0000 10,0000
8 Seafood 12 62,5000 6,0000