Продолжается подписка на наши издания! Вы не забыли подписаться?

Использование строго типизированного доступа к данным в Visual Studio 2005 и ASP.NET 2.0

Автор: Joseph Chancellor
Опубликовано: 17.04.2007

"Never put off until run time what can be done at compile time."
David Gries, Compiler Construction for Digital Computers

Введение

Когда мы, как разработчики, изучаем новые технологии, примеры могут оказаться нашими злейшими врагами. Обучалки рассчитаны на простоту понимания, но одновременно они зачастую прививают ленивые, неэффективные и даже потенциально опасные практики программирования. И нигде это так не распространено, как в примерах к ADO.NET. В этой статье мы попробуем рассмотреть, что это значит для строго типизированных объектов из вашей БД, и почему, несмотря на отсутствие примеров, вы почти всегда будете в приложениях поступать именно так.

В частности, мы рассмотрим, как создать и использовать строго типизированные DataSet-ы в Visual Studio 2005. Как будет показано, строго типизированные DataSet-ы имеют ряд преимуществ перед альтернативным, не строго типизированным доступом к данным, а с помощью Visual Studio 2005 создавать и использовать строго типизированные DataSet-ы просто, как никогда. Оставайтесь с нами!

Основы и достоинства строго типизированных объектов

Чтобы понять, что значит строго типизировать что-то, рассмотрим ситуацию со знакомствами. Если вы одиноки, с кем бы вы хотели встретиться? У вас может быть определенный критерий (богатая и красивая), а может быть и неопределенный (живая и дышит). Каковы бы ни были ваши собственные качества, у вас, несомненно, есть некий стандарт, которого вы и придерживаетесь, выбирая, с кем проводить время. Если вы достаточно мудры, список пожеланий оградит вас от ненужных болезненных эмоциональных травм. Вы можете, например, обнаружить, что серьезные отношения с алкоголиками – готовый рецепт непредсказуемости и нестабильности. Поскольку заставить кого-то измениться – дело болезненное и неэффективное, мудрость подскажет вам прекратить отношения еще до их начала. Добавив в список критериев «не алкоголик», вы тем самым сбережете время и нервы для лучших кандидатов

Каким боком эта аналогия касается программирования? Оставайтесь с нами, читатель! Объекты ADO.NET для доступа к данным рассчитаны на максимальную гибкость. До поры до времени вы будете работать со множеством простых, не типизированных объектов – настолько общих, насколько позволит .NET Framework. Используя приведенную выше аналогию, постоянно рассматривать реляционные данные как общие объекты, слегка похоже на допущение «С кем-нибудь да встречусь». Можно ли быть менее конкретным? Вы же даже не ограничили выборку живыми существами, не говорю уж – людьми! По-дружески предупреждаю вас, будьте разборчивее!

Так же, как неразборчивость в связях может привести к проблемам в будущем, излишняя свобода для объектов может привести к ошибкам в коде. Кроме того, поскольку вы разрешаете любому старому объекту отплясывать что угодно в ваших программах, вы и не узнаете о проблеме до самого исполнения приложения в рантайме. В нашей аналогии со свиданием, обнаружение ошибки во время исполнения аналогично ссоре со скандалом посреди модного итальянского ресторана. Да, проблема найдена, но если немного думать на будущее, можно и не выставлять себя на посмешище перед посетителями ресторана, и остаться без макаронов на ушах. Если применить к коду несколько более строгие стандарты, ошибки удастся отловить до запуска приложения – во время компиляции. Рассмотрим, например, следующий код:

string FirstName = myrow.("FirstName").ToString(); 

DataRow в этом примере не типизирован, и в результате вам приходится обращаться к нужному вам значению по строковому имени колонки (или, возможно, по индексу колонки в коллекции колонок записи). Будем надеяться, что такая колонка действительно существует. Тип данных колонки DataRow - object; мы предполагаем, что нижележащий тип данных колонки FirstName - string, но нам придется явно конвертировать его в строку, чтобы использовать. Если изменится имя колонки (например, на PersonFirstName), компилятор не сможет ни о чем вас оповестить. Впечатляет? А не должно бы. Ваша жизнь стала бы несколько проще, а код – надежнее, если бы код выглядел как-то так:

string FirstName = PersonRow.FirstName; 

Во втором примере у нас есть строго типизированная строка и мы знаем что свойство FirstName имеет тип string. Здесь нет никаких бестолковых имен колонок в строковом виде, и нет безалаберных преобразований объектов. Компилятор проверяет за нас типы, и мы можем заняться другими делами, не заботясь о том, правильно ли написали имя колонки.

При прочих равных условиях, никогда не стоит использовать более общий объект там, где можно использовать более специфичный. Но подождите минутку. Откуда взялся строго тпизированный объект? Хотел бы я сказать, что такие объекты создаются для вас автоматически. Однако строгая типизация, как и обзаведение хорошей любовницей, стоит некоторых усилий. Хорошие же новости в том, что лишние затраты времени окупаются, так как экономят экспоненциально больше времени при отлове багов в будущем.

Есть несколько способов строгой типизации, и в оставшейся части статьи мы обсудим, как создавать строго типизированные DataSet-ы в Visual Studio 2005. Кроме того, мы рассмотрим их достоинства и недостатки, а также некоторые альтернативы им. xodbox

Создание строго типизированных DataSet-ов в Visual Studio 2005

Строго типизированные DataSet-ы – это просто обычные DataSet-ы, но их колонки и таблицы определены заранее, и компилятор знает, что в них должно содержаться. Вместо обертки, свободной, как варежка, строго типизированные DataSet-ы обтягивают их как перчатка. Каждая последующая версия Visual Studio упрощает процесс строгой типизации DataSet-ов. В данном примере мы будем использовать БД AdventureWorks из SQL Server 2005. Выполните следующие шаги:

  1. Откройте Visual Studio и создайте новый ASP.NET Website.
  2. В Solution Explorer выберите DataSet из контекстного меню. Назовите его AdventureWorks.xsd (см. рисунок 1). Visual Studio предложит поместить файл DataSet-а в папку App_Code, разрешите ему создать такую папку.
  3. После открытия в режиме разработки AdventureWorks.xsd запустится TableAdapter Configuration Wizard. На этот раз нажмите Cancel, поскольку таблицы мы будем добавлять, перетаскивая их из Server Explorer.
  4. Откройте Server Explorer Toolbox, и перейдите к БД AdventureWorks SQL Server 2005. (если эта БД у вас не установлена, скачайте ее со страницы SQL Server 2005 Samples and Sample Databases, www.microsoft.com/downloads/details.aspx?FamilyID=E719ECF7-9F46-4312-AF89-6AD8702E4E6E&displaylang=en)
  5. Перетащите таблицы SalesOrderHeader и SalesOrderDetail в окно DataSet Designer. После этого окно должно выглядеть так, как показано на рисунке 1. Что мы видим? Для каждой добавленной таблицы Visual Studio создала строго типизированную DataTable (с именем, основанным на имени исходной таблицы) и TableAdapter. В DataTable колонки уже определены. TableAdapter – это объект, который мы будем использовать при заполнении таблицы. У нас есть используемый по умолчанию метод Fill(), который находит каждую строку из данной таблицы.


Рисунок 1.

Этот строго типизированный DataSet, как он есть, возвратит все записи из этих двух таблиц. Поскольку БД AdventureWorks содержит массу информации о заказах, почему бы не создать более точный запрос? Чтобы получить более конкретный набор записей из таблиц, можно добавить методы в объект TableAdapter. Щелкните правой кнопкой по SalesOrderHeaderTableAdapter и выберите Add | Query. Выберите "Use SQL statements" и нажмите кнопку Next. Теперь выберите "SELECT which returns rows" и нажмите Next. Наконец, введите в окне следующий запрос (или используйте для этого Query Builder):

SELECT
     SalesOrderID, RevisionNumber, OrderDate, DueDate, ShipDate, 
     Status, OnlineOrderFlag, SalesOrderNumber, PurchaseOrderNumber, 
     AccountNumber, CustomerID, ContactID, SalesPersonID, TerritoryID, 
     BillToAddressID, ShipToAddressID, ShipMethodID, CreditCardID, 
     CreditCardApprovalCode, CurrencyRateID, SubTotal, TaxAmt, Freight, 
     TotalDue, Comment, rowguid, ModifiedDate

FROM Sales.SalesOrderHeader
WHERE (OrderDate > @OrderDate)

Это простой SQL-запрос SELECT с параметром @OrderDate, сужающим выборку. Это предохранит нас от получения всех заказов, хранящихся в БД. Выбрав "Fill a DataTable" и "Return a DataTable", нажмите Finish. После добавления этого SELECT-запроса, этот запрос появится в дизайнере, в SalesOrderHeaderTableAdapter, как показано на рисунке 2.


Рисунок 2.

Использование строго типизированных DataSet-ов в ASP.NET-страницах

Создав строго типизированный DataSet, мы можем легко вывести эти данные на ASP.NET-страницу с помощью всего нескольких строк кода. Начните с создания ASP.NET-страницы на своем сайте. Затем перетащите на страницу control GridView, оставив его ID GridView1. Перейдите к коду ASP.NET-страницы и импортируйте пространство имен AdventureWorksTableAdapters (в C# синтаксис using AdventureWorksTableAdapters;) Добавьте следующий код в обработчик события Page_Load:

// Создание SalesOrderHeaderTableAdapter
SalesOrderHeaderTableAdapter salesAdapter = 
    new SalesOrderHeaderTableAdapter();

// Выборка заказов с 1 июля 2004
AdventureWorks.SalesOrderHeaderDataTable Orders = 
    salesAdapter.GetDataBy(new DateTime(2004, 7, 1));

// Привязка результатов к GridView
this.GridView1.DataSource = Orders;
this.GridView1.DataBind();


Рисунок 3.

Этот код очень прост. Мы создаем экземпляр SalesOrderHeaderTableAdapter, который и будем использовать для заполнения DataTable. Заметьте, что вместо объявления обобщенного DataTable мы объявляем объект типа SalesOrderHeaderDataTable. Чтобы заполнить DataTable, мы вызываем метод GetDateBy() и передаем ему объект DateTime. Заметьте также, что благодаря передаче объекта DateTime, а не обобщенного объекта, даже команда выборки строго типизирована. Результат выполнения этого кода приведен на рисунке 3.

В дополнение к привязке результатов к GridView с помощью кода, можно также использовать ObjectDataSource, задавая его свойству TypeName значение AdventureWorksTableAdapters.SalesOrderHeaderTableAdapter, а SelectMethod – GetData или GetDataBy.

Кроме того, что не придется писать код для доступа к БД, огромное преимущество использования строго типизированных DataSet-ов состоит в том, что в коде не спрятано никаких строковых имен колонок, которые не может проверить компилятор. Нам не придется выполнять никаких преобразований объектов. Если мы когда-нибудь изменим схему БД, то, обновив файл AdventureWorks.xsd, мы заметим все неполадки уже на этапе компиляции.

Другие способы создания строго типизированных приложений для доступа к данным

Есть и другие методы реализации строгой типизации в приложениях. Можно создать классы, более легковесные, чем DataSet-ы, и точно соответствующие вашей БД. Есть независимые разработчики, создающие инструменты для автоматизации этого процесса. В частности, есть LLBLGen Pro, который мне очень нравится, я даже книгу о нем написал: «Rapid C# Windows Development: Visual Studio 2005, SQL Server 2005, and LLBLGen Pro». Другое популярное средство – CodeSmith. Даже Microsoft работает над похожим средством по имени DLINQ, но оно еще в бета-версии и вряд ли выйдет в течение ближайшего года.

Если вы используете строго типизированные DataSet-ы из Visual Studio, вам не понадобится никакого дополнительного ПО, что, конечно, хорошо. Все перечисленные решения имеют различные возможности и достоинства, но главное в том, что строгая типизация реляционных данных увеличивает надежность и уменьшает время, затрачиваемое на отладку, а также количество ошибок. Кроме того, упрощается проверка влияния изменений схемы БД. Надеюсь, вы оцените все преимущества строгой типизации. Удачи в работе!


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

Copyright © 1994-2016 ООО "К-Пресс"