Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
При работе с базой данных обычно запрашивать данные, распределенные по нескольким таблицам. Чтобы получить данные из двух разных таблиц, можно использовать либо коррелированные вложенные запросы, либо операцию JOIN. В этом руководстве мы сравниваем коррелированные вложенные запросы и синтаксис JOIN, прежде чем узнать, как создать TableAdapter, включающий JOIN в его основной запрос.
Введение
С реляционными базами данных данные, с которыми мы заинтересованы в работе, часто распределяются по нескольким таблицам. Например, при отображении сведений о продукте мы, скорее всего, хотим вывести список соответствующих категорий и имен поставщиков каждого продукта. Таблица Products
содержит CategoryID
и SupplierID
значения, но фактические имена категорий и поставщиков находятся в таблицах Categories
и Suppliers
соответственно.
Чтобы получить информацию из другой связанной таблицы, можно использовать сопоставленные вложенные запросы или JOIN
s. Коррелированный подзапрос — это вложенный SELECT
запрос, ссылающийся на столбцы во внешнем запросе. Например, в руководстве «Создание уровня доступа к данным» мы использовали два коррелированных подзапроса в основном запросе ProductsTableAdapter
, чтобы вернуть названия категорий и имен поставщиков для каждого продукта. Это JOIN
конструкция SQL, которая объединяет связанные строки из двух разных таблиц. Мы использовали JOIN
в руководстве Запрос данных с элементом управления SqlDataSource для отображения сведений о категориях вместе с каждым товаром.
Причина, по которой мы воздержались от использования тегов JOIN
с TableAdapters, заключается в ограничениях мастера TableAdapters на автоматическое создание соответствующих инструкций INSERT
, UPDATE
и DELETE
. В частности, если основной запрос TableAdapter содержит любые JOIN
's, то TableAdapter не может автоматически создавать нерегламентированные инструкции SQL или хранимые процедуры для его свойств InsertCommand
, UpdateCommand
и DeleteCommand
.
В этом руководстве мы кратко сравним и противопоставим коррелированные подзапросы и JOIN
перед тем, как изучить, как создать TableAdapter, который включает JOIN
в свой основной запрос.
Сравнение и противопоставление коррелированных вложенных запросов иJOIN
s
Помните, что ProductsTableAdapter
, созданный в первом руководстве в Northwind
Наборе данных, использует коррелированные вложенные запросы для возвращения соответствующей категории и названия поставщика для каждого продукта. Ниже показан основной ProductsTableAdapter
запрос.
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
(SELECT CategoryName FROM Categories WHERE Categories.CategoryID =
Products.CategoryID) as CategoryName,
(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID =
Products.SupplierID) as SupplierName
FROM Products
Два коррелированных вложенных запроса — (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID)
и (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID)
— представляют собой SELECT
запросы, возвращающие одно значение для каждого продукта в качестве дополнительного столбца в списке столбцов внешней SELECT
инструкции.
Кроме того, JOIN
можно использовать для возврата имени поставщика и категории каждого продукта. Следующий запрос возвращает те же выходные данные, что и приведенный выше, но использует JOIN
s вместо вложенных запросов:
SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
Categories.CategoryName,
Suppliers.CompanyName as SupplierName
FROM Products
LEFT JOIN Categories ON
Categories.CategoryID = Products.CategoryID
LEFT JOIN Suppliers ON
Suppliers.SupplierID = Products.SupplierID
Объединяет JOIN
записи из одной таблицы с записями из другой таблицы на основе некоторых критериев. Например, LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID
в приведенном выше запросе SQL Server указывает SQL Server объединить каждую запись продукта с записью категории, значение которой CategoryID
соответствует значению CategoryID
продукта. Объединенный результат позволяет работать с соответствующими полями категорий для каждого продукта (например CategoryName
, ).
Замечание
JOIN
часто используются для запросов данных из реляционных баз данных. Если вы не знакомы с JOIN
синтаксисом или вам нужно немного приступить к его использованию, я бы рекомендовал руководство по присоединению к SQL в Школах W3. Кроме того, стоит ознакомиться с JOIN
разделами "Основы " и "Основы субзапроса " в электронной документации ПО SQL.
Так как и JOIN
вложенные запросы, и связанные подзапросы могут использоваться для получения соответствующих данных из других таблиц, многие разработчики ломают голову и задаются вопросом, какой подход выбрать. Все гуру SQL, с которыми я разговаривал, говорили примерно одно и то же, что это не особенно влияет на производительность, так как SQL Server создаёт примерно одинаковые планы выполнения. Их совет заключается в том, чтобы использовать технику, с которой вы и ваша команда чувствуете себя наиболее комфортно. Стоит отметить, что после того, как дают этот совет, эти эксперты немедленно выражают свое предпочтение JOIN
по сравнению с коррелированными вложенными запросами.
При создании уровня доступа к данным с помощью типизированных наборов данных средства лучше работают при использовании вложенных запросов. В частности, мастер TableAdapter не будет автоматически создавать соответствующие инструкции INSERT
, UPDATE
и операторы DELETE
, если основной запрос содержит какие-либо JOIN
, но автоматически создает их при использовании сопоставленных вложенных запросов.
Чтобы изучить этот недостаток, создайте временный типизированный набор данных в папке ~/App_Code/DAL
. В мастере настройки TableAdapter выберите использование нерегламентированных инструкций SQL и введите следующий SELECT
запрос (см. рис. 1).
SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
Categories.CategoryName,
Suppliers.CompanyName as SupplierName
FROM Products
LEFT JOIN Categories ON
Categories.CategoryID = Products.CategoryID
LEFT JOIN Suppliers ON
Suppliers.SupplierID = Products.SupplierID
Рис. 1. Введите основной запрос, содержащий JOIN
s (щелкните, чтобы просмотреть изображение полного размера)
По умолчанию TableAdapter автоматически создает INSERT
, UPDATE
операторы и DELETE
инструкции на основе основного запроса. Если нажать кнопку "Дополнительно", вы увидите, что эта функция включена. Несмотря на этот параметр, TableAdapter не сможет создать операторы INSERT
, UPDATE
и DELETE
, так как основной запрос содержит JOIN
.
Рис. 2. Введите основной запрос, содержащий JOIN
s
Нажмите кнопку "Готово", чтобы завершить работу мастера. На этом этапе Конструктор DataSet будет включать один TableAdapter с DataTable, содержащей столбцы для каждого из полей, возвращаемых в списке столбцов запроса SELECT
. Это включает в себя CategoryName
и SupplierName
, как показано на рисунке 3.
Рис. 3. Таблица данных содержит столбец для каждого поля, возвращаемого в списке столбцов.
Хотя DataTable имеет нужные столбцы, TableAdapter не имеет значений для своих свойств InsertCommand
, UpdateCommand
и DeleteCommand
. Чтобы подтвердить это, щелкните TableAdapter в конструкторе и перейдите в окно "Свойства". Там вы увидите, что свойства InsertCommand
, UpdateCommand
и DeleteCommand
установлены на (None).
Рис. 4. Для свойств InsertCommand
, UpdateCommand
, и DeleteCommand
задано значение (Нет) (Щелкните здесь, чтобы просмотреть изображение в полном размере)
Чтобы обойти этот недостаток, мы можем вручную указать инструкции и параметры SQL для InsertCommand
объекта, UpdateCommand
и DeleteCommand
свойства через окно свойств. Кроме того, мы могли бы начать с настройки основного запроса TableAdapter, чтобы не включать ни один JOIN
. Это позволит INSERT
, UPDATE
и DELETE
автоматически создавать инструкции для нас. После завершения работы мастера, мы могли бы затем вручную обновить TableAdapter в SelectCommand
окне свойств, чтобы он содержал JOIN
синтаксис.
Хотя этот подход работает, он очень нестабилен при использовании нерегламентированных запросов SQL, потому что каждый раз, когда основной запрос TableAdapter перенастраивается через мастер, автоматически созданные инструкции INSERT
, UPDATE
и DELETE
создаются повторно. Это означает, что все настройки, которые мы сделали позже, будут потеряны, если щелкнуть правой кнопкой мыши по TableAdapter, выбрать "Настроить" в контекстном меню и снова завершить мастер.
Хрупкость автоматически созданных INSERT
TableAdapter, UPDATE
, и DELETE
инструкций, к счастью, ограничена неформальными SQL инструкциями. Если ваш TableAdapter использует хранимые процедуры, вы можете настроить хранимые процедуры SelectCommand
, InsertCommand
, UpdateCommand
и DeleteCommand
, а затем повторно запустить мастер конфигурации TableAdapter, не опасаясь, что хранимые процедуры будут изменены.
На следующих нескольких шагах мы создадим TableAdapter, который изначально использует основной запрос, пропускающий любые JOIN
, чтобы соответствующие хранимые процедуры вставки, обновления и удаления были автоматически созданы. Затем мы обновим SelectCommand
так, чтобы он использовал JOIN
, который возвращает дополнительные столбцы из связанных таблиц. Наконец, мы создадим соответствующий класс уровня бизнес-логики и продемонстрировать использование TableAdapter на веб-странице ASP.NET.
Шаг 1. Создание tableAdapter с помощью упрощенного основного запроса
В этом руководстве мы добавим элементы TableAdapter и строго типизированный элемент DataTable для таблицы Employees
в NorthwindWithSprocs
Наборе данных. Таблица Employees
содержит ReportsTo
поле, указывающее EmployeeID
руководителя сотрудника. Например, сотрудница Энн Додсворт имеет значение ReportTo
5, что является значением EmployeeID
Стивена Бьюкенена. Таким образом, Энн сообщает Стивену, её менеджеру. Вместе со сведениями о значении каждого сотрудника ReportsTo
может быть полезно также узнать имя его руководителя. Это можно сделать с помощью JOIN
. Однако использование JOIN
при первоначальном создании TableAdapter мешает мастеру автоматически создавать соответствующие возможности вставки, обновления и удаления. Поэтому мы начнем с создания TableAdapter, основной запрос которого не содержит никаких JOIN
s. Затем на втором шаге мы обновим основную процедуру хранимого запроса, чтобы получить имя руководителя с помощью JOIN
.
Начните с открытия NorthwindWithSprocs
набора данных в папке ~/App_Code/DAL
. Щелкните правой кнопкой мыши на Конструкторе, выберите опцию "Добавить" в контекстном меню, а затем пункт меню TableAdapter. Откроется мастер настройки TableAdapter. Как показано на рисунке 5, создайте новые хранимые процедуры с помощью мастера, затем нажмите кнопку "Далее". Чтобы освежить знания о создании новых хранимых процедур с помощью мастера TableAdapter, ознакомьтесь с руководством по созданию новых хранимых процедур для TableAdapter типизированного DataSet.
Рис. 5. Выберите параметр "Создать новые хранимые процедуры" (щелкните, чтобы просмотреть изображение полного размера)
Используйте следующую SELECT
инструкцию для основного запроса TableAdapter:
SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees
Так как этот запрос не содержит JOIN
, мастер TableAdapter автоматически создаст хранимые процедуры с соответствующими операторами INSERT
, UPDATE
и DELETE
, а также хранимую процедуру для выполнения основного запроса.
На следующем шаге мы назовем хранимые процедуры TableAdapter. Используйте именаEmployees_Select
, Employees_Insert
Employees_Update
иEmployees_Delete
, как показано на рис. 6.
Рис. 6. Назовите хранимые процедуры TableAdapter (щелкните, чтобы просмотреть изображение полного размера)
Последний шаг предложит нам назвать методы TableAdapter. Используйте Fill
и GetEmployees
в качестве имен методов. Также не забудьте оставить флажок "Создать методы" для отправки обновлений непосредственно в базу данных (GenerateDBDirectMethods).
Рис. 7. Назовите методы Fill
TableAdapter и GetEmployees
(Щелкните, чтобы просмотреть изображение полного размера)
Завершив работу мастера, ознакомьтесь с хранимыми процедурами в базе данных. Вы должны увидеть четыре новых: Employees_Select
, Employees_Insert
, Employees_Update
и Employees_Delete
. Затем проверьте только что созданные EmployeesDataTable
и EmployeesTableAdapter
. DataTable содержит столбец для каждого поля, возвращаемого основным запросом. Щелкните tableAdapter и перейдите в окно "Свойства". Там вы увидите, что свойства InsertCommand
, UpdateCommand
и DeleteCommand
правильно настроены для вызова соответствующих хранимых процедур.
Рис. 8. TableAdapter включает возможности вставки, обновления и удаления (щелкните здесь, чтобы просмотреть изображение в полном размере)
При автоматическом создании хранимых процедур для вставки, обновления и удаления, а также при правильной настройке свойств InsertCommand
, UpdateCommand
и DeleteCommand
, мы готовы настроить хранимую процедуру SelectCommand
, чтобы возвращать дополнительные сведения о менеджере каждого сотрудника. В частности, необходимо обновить Employees_Select
хранимую процедуру, чтобы использовать JOIN
и возвращать значения менеджера: FirstName
и LastName
. После того как хранимая процедура будет обновлена, нам потребуется обновить DataTable, чтобы он включал эти дополнительные столбцы. Мы рассмотрим эти две задачи в шагах 2 и 3.
Шаг 2. Настройка хранимой процедуры для того, чтобы включитьJOIN
Начните, перейдя в обозреватель серверов, развернув папку хранимых процедур базы данных Northwind и открыв хранимую процедуру Employees_Select
. Если эта хранимая процедура не отображается, щелкните правой кнопкой мыши папку хранимых процедур и выберите "Обновить". Обновите хранимую процедуру, чтобы она использовала LEFT JOIN
для возврата имени и фамилии руководителя.
SELECT Employees.EmployeeID, Employees.LastName,
Employees.FirstName, Employees.Title,
Employees.HireDate, Employees.ReportsTo,
Employees.Country,
Manager.FirstName as ManagerFirstName,
Manager.LastName as ManagerLastName
FROM Employees
LEFT JOIN Employees AS Manager ON
Employees.ReportsTo = Manager.EmployeeID
После обновления инструкции SELECT
сохраните изменения, перейдя в меню "Файл" и выбрав "Сохранить Employees_Select
". Кроме того, можно щелкнуть значок "Сохранить" на панели инструментов или нажать клавиши CTRL+S. После сохранения изменений щелкните правой кнопкой мыши Employees_Select
хранимую процедуру в обозревателе серверов и выберите "Выполнить". При этом выполняется хранимая процедура и отображаются результаты в окне вывода (см. рис. 9).
Рис. 9. Результаты хранимых процедур отображаются в окне вывода (щелкните, чтобы просмотреть изображение полного размера)
Шаг 3. Обновление столбцов DataTable
На этом этапе процедура хранимая Employees_Select
возвращает значения ManagerFirstName
и ManagerLastName
, но в EmployeesDataTable
отсутствуют столбцы. Эти отсутствующие столбцы можно добавить в DataTable одним из двух способов:
- Вручную щелкните правой кнопкой мыши dataTable в конструкторе наборов данных и в меню "Добавить" выберите столбец. Затем можно присвоить столбцу имя и задать его свойства соответствующим образом.
-
Автоматически — мастер настройки TableAdapter обновит столбцы DataTable, чтобы отразить поля, возвращаемые хранимой
SelectCommand
процедурой. При использовании нерегламентированных инструкций SQL мастер также удаляет свойстваInsertCommand
,UpdateCommand
иDeleteCommand
, так как теперьSelectCommand
содержит объектJOIN
. Но при использовании хранимых процедур эти свойства команд остаются неизменными.
Мы изучили вручную добавление столбцов DataTable в предыдущих руководствах, включая master/Details Using a Bulleted List of Master Records with a Details DataList and Uploading Files, и мы рассмотрим этот процесс еще раз в следующем руководстве. Однако в этом руководстве мы будем использовать автоматический подход с помощью мастера настройки TableAdapter.
Начните, щелкнув EmployeesTableAdapter
правой кнопкой мыши и выбрав "Настроить" в контекстном меню. Откроется мастер настройки TableAdapter, в котором перечислены хранимые процедуры, используемые для выбора, вставки, обновления и удаления, а также их возвращаемых значений и параметров (при наличии). На рисунке 10 показан этот мастер. Здесь мы видим, что Employees_Select
хранимая процедура теперь возвращает ManagerFirstName
и ManagerLastName
поля.
Рис. 10. Мастер отображает обновленный список столбцов для Employees_Select
хранимой процедуры (щелкните, чтобы просмотреть изображение полного размера)
Завершите работу мастера, нажав кнопку "Завершить". После возвращения в конструктор наборов данных EmployeesDataTable
включает два дополнительных столбца: ManagerFirstName
и ManagerLastName
.
Рис. 11. Содержит EmployeesDataTable
два новых столбца (щелкните, чтобы просмотреть изображение полного размера)
Чтобы показать, что обновленная хранимая процедура Employees_Select
действует и что возможности вставки, обновления и удаления TableAdapter по-прежнему работают, создадим веб-страницу, которая позволит пользователям просматривать и удалять сотрудников. Прежде чем создавать такую страницу, необходимо сначала создать новый класс на уровне бизнес-логики для работы с сотрудниками из NorthwindWithSprocs
набора данных. На шаге 4 мы создадим EmployeesBLLWithSprocs
класс. На шаге 5 мы будем использовать этот класс на странице ASP.NET.
Шаг 4. Реализация уровня бизнес-логики
Создайте файл класса в папке ~/App_Code/BLL
с именем EmployeesBLLWithSprocs.vb
. Этот класс имитирует семантику существующего EmployeesBLL
класса, только этот новый предоставляет меньше методов и использует NorthwindWithSprocs
Набор данных (вместо Northwind
Набора данных). Добавьте в класс EmployeesBLLWithSprocs
приведенный далее код.
Imports NorthwindWithSprocsTableAdapters
<System.ComponentModel.DataObject()> _
Public Class EmployeesBLLWithSprocs
Private _employeesAdapter As EmployeesTableAdapter = Nothing
Protected ReadOnly Property Adapter() As EmployeesTableAdapter
Get
If _employeesAdapter Is Nothing Then
_employeesAdapter = New EmployeesTableAdapter()
End If
Return _employeesAdapter
End Get
End Property
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Select, True)> _
Public Function GetEmployees() As NorthwindWithSprocs.EmployeesDataTable
Return Adapter.GetEmployees()
End Function
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Delete, True)> _
Public Function DeleteEmployee(ByVal employeeID As Integer) As Boolean
Dim rowsAffected = Adapter.Delete(employeeID)
'Return true if precisely one row was deleted, otherwise false
Return rowsAffected = 1
End Function
End Class
Свойство EmployeesBLLWithSprocs
класса Adapter
возвращает экземпляр NorthwindWithSprocs
набора данных EmployeesTableAdapter
. Это используется методами класса GetEmployees
и DeleteEmployee
. Метод GetEmployees
вызывает соответствующий EmployeesTableAdapter
метод GetEmployees
, который вызывает хранимую процедуру Employees_Select
и заполняет результаты в EmployeeDataTable
. Метод DeleteEmployee
аналогично вызывает EmployeesTableAdapter
метод s Delete
, который вызывает хранимую процедуру Employees_Delete
.
Шаг 5. Работа с данными на уровне презентации
EmployeesBLLWithSprocs
После завершения класса мы готовы работать с данными сотрудников с помощью страницы ASP.NET. Откройте страницу JOINs.aspx
в папке AdvancedDAL
и перетащите GridView из панели элементов в конструктор, присвоив свойству ID
значение Employees
. Затем из смарт-тега GridView привязать сетку к новому элементу управления ObjectDataSource с именем EmployeesDataSource
.
Настройте ObjectDataSource для использования класса EmployeesBLLWithSprocs
, и на вкладках SELECT и DELETE, убедитесь, что методы GetEmployees
и DeleteEmployee
выбраны из раскрывающихся списков. Нажмите кнопку "Готово", чтобы завершить настройку ObjectDataSource.
Рис. 12. Настройка ObjectDataSource для использования EmployeesBLLWithSprocs
класса (щелкните, чтобы просмотреть изображение полного размера)
Рис. 13: Использование ObjectDataSource, используя методы GetEmployees
и DeleteEmployee
(нажмите, чтобы просмотреть изображение полного размера)
Visual Studio добавит BoundField в GridView для каждого столбца EmployeesDataTable
. Удалите все эти поля BoundFields, за исключением Title
, LastName
, FirstName
, ManagerFirstName
, и переименуйте свойства ManagerLastName
и HeaderText
последних четырех BoundFields на "Фамилия", "Имя", "Имя менеджера" и "Фамилия менеджера" соответственно.
Чтобы разрешить пользователям удалять сотрудников на этой странице, необходимо выполнить две действия. Во-первых, настройте GridView, чтобы предоставить возможность удаления, выбрав параметр "Включить возможность удаления" из его смарт-тега. Во-вторых, измените свойство ObjectDataSource из значения, заданного мастером ObjectDataSource OldValuesParameterFormatString
(original_{0}
) на значение по умолчанию ({0}
). После внесения этих изменений декларативная разметка GridView и ObjectDataSource должны выглядеть следующим образом:
<asp:GridView ID="Employees" runat="server" AutoGenerateColumns="False"
DataKeyNames="EmployeeID" DataSourceID="EmployeesDataSource">
<Columns>
<asp:CommandField ShowDeleteButton="True" />
<asp:BoundField DataField="Title"
HeaderText="Title"
SortExpression="Title" />
<asp:BoundField DataField="LastName"
HeaderText="Last Name"
SortExpression="LastName" />
<asp:BoundField DataField="FirstName"
HeaderText="First Name"
SortExpression="FirstName" />
<asp:BoundField DataField="ManagerFirstName"
HeaderText="Manager's First Name"
SortExpression="ManagerFirstName" />
<asp:BoundField DataField="ManagerLastName"
HeaderText="Manager's Last Name"
SortExpression="ManagerLastName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="EmployeesDataSource" runat="server"
DeleteMethod="DeleteEmployee" OldValuesParameterFormatString="{0}"
SelectMethod="GetEmployees" TypeName="EmployeesBLLWithSprocs">
<DeleteParameters>
<asp:Parameter Name="employeeID" Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>
Проверьте страницу, перейдя к ней через браузер. Как показано на рисунке 14, страница будет содержать список каждого сотрудника и имя его или её руководителя, если таковой имеется.
Рис. 14. В JOIN
Employees_Select
хранимой процедуре возвращается имя менеджера (щелкните, чтобы увеличить изображение)
Нажатие кнопки "Удалить" запускает рабочий процесс удаления, который завершается выполнением Employees_Delete
хранимой процедуры. Однако попытка DELETE
инструкции в хранимой процедуре завершается сбоем из-за нарушения ограничения внешнего ключа (см. рис. 15). В частности, у каждого сотрудника есть одна или несколько записей в Orders
таблице, что приводит к сбою удаления.
Рис. 15. Удаление сотрудника с соответствующими заказами приводит к нарушению ограничения внешнего ключа (щелкните, чтобы просмотреть изображение полного размера)
Чтобы разрешить удалению сотрудника, можно выполнить следующие действия.
- Обновите ограничение внешнего ключа для разрешения каскадных удалений.
- Вручную удалите записи из
Orders
таблицы для сотрудников, которые вы хотите удалить, или -
Employees_Delete
Обновите хранимую процедуру, чтобы сначала удалить связанные записи изOrders
таблицы перед удалениемEmployees
записи. Мы обсудили этот метод в руководстве по использованию существующих хранимых процедур для typed DataSet s TableAdapters .
Я оставлю это как упражнение для читателя.
Сводка
При работе с реляционными базами данных обычно запросы извлекают данные из нескольких связанных таблиц. Коррелированные вложенные запросы и JOIN
предоставляют два различных метода доступа к данным из связанных таблиц в запросе. В предыдущих руководствах мы чаще всего использовали коррелированные подзапросы, так как TableAdapter не может автоматически создавать операторы INSERT
, UPDATE
, и DELETE
для запросов, включающих JOIN
. Хотя эти значения можно указать вручную, при использовании нерегламентированных инструкций SQL все настройки будут перезаписаны при завершении мастера настройки TableAdapter.
К счастью, TableAdapters, созданные с помощью хранимых процедур, не страдают от той же хрупкости, что и созданные с помощью нерегламентированных инструкций SQL. Поэтому можно создать TableAdapter, основной запрос которого используется JOIN
при использовании хранимых процедур. В этом руководстве мы узнали, как создать такой объект TableAdapter. Мы начали использовать JOIN
запрос -less SELECT
для основного запроса TableAdapter, чтобы соответствующие процедуры вставки, обновления и удаления хранимых процедур были созданы автоматически. После завершения начальной конфигурации TableAdapter мы изменили SelectCommand
хранимую процедуру, чтобы она использовала JOIN
, и повторно запустили мастер конфигурации TableAdapter для обновления столбцов EmployeesDataTable
.
Повторное выполнение мастера настройки TableAdapter автоматически обновило столбцы EmployeesDataTable
, чтобы отразить поля данных, возвращаемые хранимой процедурой Employees_Select
. Кроме того, эти столбцы можно было добавить вручную в DataTable. В следующем руководстве мы рассмотрим ручное добавление столбцов в DataTable.
Счастливое программирование!
Сведения о авторе
Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С ним можно связаться по адресу mitchell@4GuysFromRolla.com.
Особое спасибо кому
Эта серия учебников была проверена многими полезными рецензентами. Основные рецензенты для этого руководства были Хилтон Гайсеноу, Дэвид Суру и Тереза Мерфи. Хотите просмотреть мои предстоящие статьи MSDN? Если да, напишите мне на mitchell@4GuysFromRolla.com.