Проектирование баз данных и работа с ними Веб-приложений. Введение в БД, SQL Server, ADO.NET
9.2.2.3. Отсоединенные наборы данных
ADO.NET предоставляет более совершенные способы организации двустороннего взаимодействия приложения с базой данных, основанной на отсоединенных наборах данных.
Основной идеей использования отсоединенных наборов данных является изменения алгоритмов взаимодействия приложения с базой данных за счет подключения к набору данных, выполнения запроса и создания копии данных на стороне клиента, отключения от БД, осуществление манипуляций с данными на стороне клиента, при необходимости внесения изменений в базу данных, подключение к ней, передача изменений и отключение. Таким образом, все основные манипуляции с данными происходят в отсоединенной наборе данных, представляющем собой копию данных, хранящихся в БД, а внесение изменений происходит в одной пакетной операции. Все это уменьшает время, в течение которого должно быть открыто соединение с БД, ускоряет работу и упрощает логику взаимодействия приложения с данными. Рассмотрим объекты ADO.NET, реализующие данный механизм.
9.2.2.3.1. Класс DataSet
Объект DataSet представляет собой контейнер, содержащий объекты DataTable и Relation. DataTable, представляет собой таблицу, состоящую из строк и столбцов. Строки таблицы представлены объектом DataRow, который, в свою очередь, представляет собой коллекцию столбцов таблицы (объект DataColumn ). Данные в DataSet отсоединены от БД. Все изменения данных кэшируются в объектах DataRow. При возникновении необходимости передачи изменений в данных объекта DataSet существует возможность передачи только изменившейся части данных, что позволяет значительно экономить ресурсы канала связи, т.к. в этом случае передается гораздо меньший объем данных. Обобщая все вышесказанное можно сделать вывод о том, что использование объекта DataSet в ряде случаев оказывается более эффективным, чем DataReader. Наиболее типичными ситуациями, в которых рекомендуется применять объект DataSet , являются:
- Необходимость реализации сериализации данных на диск. DataSet позволяет легко сохранять данные в файле XML. При этом возможны варианты сохранения только данных, только структуры данных, либо и того и другого.
- Необходимость организации навигации по набору данных в двух направлениях. Как уже упоминалось, DataReader обеспечивает перемещение по набору только вперед. С помощью же DataSet возможна организация постраничного просмотра данных.
- Необходима привязка нескольких элементов управления к одному набору данных. DataSet, в отличие от DataReader содержит средства организации сортировки и фильтрации данных.
Для извлечения данных из базы данных и наполнения ими объекта DataSet необходимо использовать еще один объект DataAdapter, который помимо прочего позволяет обновлять данные БД на основе внесенных в DataSet изменений.
9.2.2.3.2. Класс DataAdapter
DataAdapter является связующим звеном между базой данных и DataSet. Точнее, он связывает БД и объект DataTable, расположенный внутри DataSet.
DataAdapter содержит три основных метода, позволяющих ему выполнять все необходимые операции, связанные с извлечением и обновлением данных (табл. 9.10).
Рассмотрим пример использования объектов DataSet и DataAdapter для извлечения данных из БД, наполнения DataSet и отображения данных на странице Веб-приложения.
Прежде всего, необходимо установить подключение к источнику данных. Для этого необходимо использовать строку подключения, а также объект Connection. Воспользуемся предыдущими примерами:
string strSqlConnection = "Data Source=localhost\\sqlexpress;Initial Catalog=FORTEST;Integrated Security=SSPI"; string sqlString = "Select * From FORTEST_Table"; SqlConnection sqlCon=new SqlConnection(strSqlConnection);
Создадим объект DataAdapter и передадим ему в качестве параметров строку запроса, а также строку подключения к БД.
SqlDataAdapter da = new SqlDataAdapter(sqlString,sqlCon);
Теперь необходимо создать объект DataSet и заполнить его данными с помощью DataAdapter.
DataSet ds = new DataSet(); da.Fill(ds, "Records");
Из приведенного примера видно, что метод Fill объекта da, в качестве параметров использует имя объекта DataSet, в который необходимо поместить данные, возвращаемые в результате выполнения запроса, определенного в строке sqlString. Во втором параметре можно указать имя, которое будет сопоставлено с таблицей, созданной в DataSet. Из примера видно, что в данном случае не используется явный вызов метода Open объекта Connection. Это объясняется тем, что данный метод вызывается неявно при исполнении метода Fill. Таким образом, DataAdapter сперва открывает соединение с БД, затем выполняет необходимые манипуляции с данными, после чего закрывает открытое ранее соединение.
9.2.2.4. Привязка и отображение данных
Большинство элементов управления ASP.NET поддерживают привязку данных. При этом привязка данных может быть как данных с одним значением, так и с множественными значениями. Привязка с одним значением означает, что элемент управления может отображать единственное значение, извлекаемое из источника данных. Такие принципы используются элементами управления TextBox, LinkButton, Image, HyperLink. Привязка с множественными значениями означает, что элемент управления может отображать несколько значений, извлекаемых из источника данных. Элементы управления, поддерживающие привязку с множественными значениями, строятся на основе списков и электронных таблиц. Типичными представителями таких элементов управления являются ListBox и GridView.
Для привязки элементов управления к источнику данных необходимо установить значение свойства DataSource, в котором указать наименование объекта, содержащего данные, необходимые для отображения. При установке свойства DataSource создается логическая связь между элементом управления, способным отображать данные и объектом данных, подлежащих отображению. После того, как источник данных определен, необходимо заполнить его данными. Для этого используется метод DataBind() элемента управления, заполняемого данными, который извлекает данные из источника, проходит в цикле по источнику, определенному в DataSource и обновляет страницу. Привязка с множественными значениями является наиболее мощным типом привязки, так как в этом случае не требуется программировать циклический перебор значений источника данных и вывод их на экран, эта логика уже реализована в элементе управления, поддерживающего множественную привязку.
Рассмотрим основные принципы использования обоих типов привязки данных.
9.2.2.4.1. Привязка с одним значением
Элементы управления, поддерживающие привязку данных с одним значением, позволяют осуществить привязку некоторых из их свойств к данным с помощью выражения привязки данных. Выражение привязки данных вводится в тексте страницы .aspx и заключается внутри ограничителей <%# %>.
В качестве выражения привязки данных может быть использована общедоступная, либо защищенная переменная, а также любое другое выражение, которое может быть вычислено в момент выполнения страницы. Так, в качестве выражения привязки данных допустимо использовать функции, свойства, объекты, определенные в классе страницы.
Для того чтобы вычислить выражение привязки, необходимо в коде приложения вызвать метод Page.DataBind(). В момент вызова данного метода, ASP.NET проверяет все выражения на текущей странице, при необходимости производит вычисления и заменяет их соответствующими значениями.
В качестве примера рассмотрим привязку элемента Label к данным таблицы FORTEST_Table. Для этого создадим метод GetRecord(), возвращающий в качестве значения содержимое первой строки столбца Column1 таблицы FORTEST_Table:
public string GetRecord() { return ds.Tables["Records"].Rows[0]["Column1"].ToString(); }
Теперь необходимо добавить элемент Label на страницу .aspx и установить выражение привязки для свойства Text данного элемента:
<asp:Label ID="Label1" runat="server" Text="<%#GetRecord()%>"></asp:Label>
И в методе Page.Load() произведем вызов метода Page.DataBind().
Как видно из данного примера, таким способом можно отобразить только одно значение какого-либо поля таблицы.
9.2.2.4.2. Привязка с множественным значением
Для отображения набора значений необходимо использовать привязку с множественным значением. Привязываемый набор значений должен содержаться в объекте, способном хранить коллекции значений (например, объекты ArrayList, Hashtable и др.).
Каждый элемент, поддерживающий возможность множественной привязки, содержит следующий набор свойств (табл. 9.11).
Принципы использования всех списковых элементов, способных отображать связанные данные, одинаковы. Для привязки такого элемента к источнику данных, необходимо установить значения свойств DataSource и DataTextField.
В следующем примере на странице размещен элемент DropDownList1, который связан с источником данных, в качестве которого выступает таблица FORTEST_Table.
DropDownList1.DataSource = ds.Tables["Columns"]; DropDownList1.DataTextField = "Column1"; DropDownList1.DataValueField = "Column2";
И в методе Page.Load() произведем вызов метода Page.DataBind().
Так как объект DataSet может содержать много таблиц, в свойстве DataSource необходимо указать имя таблицы, к которой необходимо осуществить привязку. Свойство DataTextField содержит наименование столбца таблицы, значения которого будут отображаться элементом управления. Свойство DataValueField является необязательным и, в данном случае, обозначает то, что при выборе значения в элементе управления, значение свойства SelectedItem этого элемента будет установлено равным значению поля Column2, соответствующего выбранной записи.
Кроме использованных списковых элементов, ASP.NET содержит также и более сложные элементы, способные привязываться к данным и отображать их. К таким элементам относятся GridView, DetailsView, FormView:
- GridView представляет собой таблицу, способную привязываться к данным и отображать содержимое таблиц. Поддерживает выбор, редактирование, сортировку и перемещение по страницам данных.
- DetailsView предназначен для показа одной записи из таблицы за один раз. Поддерживает редактирование и перемещение по страницам.
- FormView практически аналогичен DetailsView с той лишь разницей, что FormView основан на шаблонах, что делает его более гибким при отображении информации.
Самым мощным элементом по количеству возможностей является GridView. Очень часто его приходится использовать для отображения информации в виде таблицы. Для привязки GridView к источнику данных необходимо установить значение свойства DataSource. В следующем примере на странице размещен объект GridView, который привязывается к таблице FORTEST_Table и отображает ее содержимое.
GridView1.DataSource = ds.Tables["Columns"];
Показанные примеры демонстрируют способы привязки к источникам данных с использованием программного кода, однако это не единственная возможность осуществить привязку элемента управления к источнику данных. Visual Studio 2005/2008 позволяет осуществить привязку с использованием визуальных средств. Для этих целей .NET Framework содержит несколько элементов управления источниками данных. Они расположены на вкладке Data панели Toolbox. Среди них такие как:
- SqlDataSource – позволяет подключаться к любому источнику данных, который имеет поставщика данных ADO.NET. К таким источникам данных относятся SQL Server, OLE DB, Oracle и другие.
- ObjectDataSource – позволяет подключаться к пользовательскому классу доступа к данным. Этот подход целесообразно применять при построении крупномасштабных и сложных приложений. Подробнее об использовании пользовательских классов доступа к данным и элементе ObjectDataSource будет рассказано в разделе, посвященном реализации трехуровневой архитектуры доступа к данным в ASP.NET.
- AccessDataSource – позволяет подключаться к базам данных Microsoft Access.
- XmlDataSource – позволяет подключаться к XML файлу.
- SiteMapDataSource – позволяет подключаться к файлу Web.Sitemap, содержащего описание навигационной структуры Веб-приложения.
9.2.2.5. Использование DataView для фильтрации и сортировки данных
При создании сложных приложений, ориентированных на активное взаимодействие с пользователями, большое значение играет отображение данных и возможности настройки этого отображения. ASP.NET предоставляет возможность такой настройки отображения извлекаемой из базы данных информации посредством использования класса DataView. Этот класс снабжен возможностью фильтрации и сортировки отображаемых данных, причем эти режимы никак не затрагивают реальные данные.
Каждый объект DataTable по умолчанию имеет ассоциированный с ним объект DataView. При этом допускается создание множества объектов DataView для создания множества представлений одной и той же таблицы. Для обращения к представлению по умолчанию объекта DataTable необходимо обратиться к свойству DataTable.DefaultView.
Рассмотрим примеры использования основных функций DataView.
9.2.2.5.1. Сортировка данных
Сценарий использования объекта DataView выглядит следующим образом:
- создание объекта DataView ;
- настройка его параметры сортировки или фильтрации;
- привязка его к элементу отображения данных;
- инициирование процесс привязки данных.
Рассмотрим пример реализации сортировки данных, извлеченных из таблицы FORTEST_Table:
protected void Page_Load(object sender, EventArgs e) { string ConnectionString = WebConfigurationManager.ConnectionStrings["FORTEST"].ConnectionString; SqlConnection con = new SqlConnection(ConnectionString); string query = "SELECT * FROM FORTEST_Table"; SqlDataAdapter da = new SqlDataAdapter(query, con); DataSet ds = new DataSet(); da.Fill(ds, "Columns"); DataView dv = new DataView(ds.Tables["Columns"]); dv.Sort = "Column1"; GridView1.DataSource = dv; Page.DataBind(); }
Как видно из примера, сортировка данных заключается просто в присваивании свойству Sort объекта DataView выражения сортировки. В данном примере, выражение сортировки состоит из имени одного столбца таблицы. В общем случае, оно может включать несколько столбцов, разделенных запятыми. По умолчанию производится сортировка в порядке возрастания значения элементов столбца. При необходимости, возможно изменение порядка сортировки.
9.2.2.5.2. Фильтрация данных
Для выполнения фильтрации данных при помощи DataView необходимо воспользоваться свойством RowFilter. Содержимое RowFilter очень напоминает команду Where запроса SQL. Здесь записывается условие фильтрации набора данных. При этом возможно использование тех же операций сравнения и логических операций, которые используются в языке SQL. Кроме того, здесь возможно выполнение простейших вычислительных операций, таких как сложение, вычитание, умножение, деление, вычисление остатка от деления.