AND C.CustomerID = O.CustomerID AND O.OrderID = OD.OrderID AND OD.ProductID = P.ProductID
GROUP BY ProductName
Параметр определяет индекс строки в таблице Customers, но работа в процедуре ведется с четырьмя таблицами базы NorthWind (Products, Order Details, Orders и Customers). Логика выбора данных сосредоточена в части WHERE оператора SELECT. Здесь происходит спуск по связанным таблицам, начиная от таблицы Customers и заканчивая таблицей Products. Цепочка обращений к данным использует первичные и связанные ключи указанных таблиц и выглядит следующим образом: Customers®Orders®Order Details®Products.
· По индексу покупателя CustomerID находятся его заказы,
· По индексу заказа OrderID определяются его детали (индекс продукта).
· По индексу продукта ProductID определяется его наименование.
· Наименование продукта поступает в первую колонку результирующей таблицы.
· Во вторую колонку помещаются суммы закупок этих продуктов клиентом с индексом CustomerID.
Рассмотрим код, который пользуется хранимой процедурой CustOrderHist и выводит результаты в консольное окно. Код клиента ("ALFKI") задан жестко, но может быть произвольным. Для демонстрации результатов явно напрашивается компонент PieChart, который мы рассматривали в предыдущем семестре.
string clientID = "ALFKI";
SqlCommand cmd = new SqlCommand ("CustOrderHist", сn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter par = cmd.Parameters.Add(
new SqlParameter("@CustomerID", SqlDbType. VarChar, 5, "CustomerID"));
par.Value = clientID;
SqlDataReader reader = cmd.ExecuteReader();
Console.WriteLine("\n{0,-32}{1}", reader.GetName(0), reader.GetName(1));
while (reader.Read())
Console.WriteLine("{0,-35}{1,2}", reader.GetString(0), reader.GetInt32(1));
reader.Close();
сn.Close();
В этот момент стоит задуматься о той работе, которую проводит ядро СУБД для реализации логики сложных запросов. В учебных целях рассмотрим код, который реализует примерно ту же логику, что и хранимая процедура, но делает постепенно, с помощью серии более простых запросов. Цель упражнения—научиться управлять параметрами команды SELECT. Сначала запросим (и запомним в коллекции orders) индексы всех заказов данного клиента.
string clientID = "ALFKI";
SqlCommand cmd = new SqlCommand(
"SELECT OrderID From Orders WHERE CustomerID=@CustomerID", cn);
SqlParameter par = cmd.Parameters.Add(new SqlParameter(
"@CustomerID", SqlDbType.VarChar, 5, "CustomerID"));
par.Value = clientID;
cn.Open();
SqlDataReader reader = cmd.ExecuteReader();
ArrayList orders = new ArrayList();
Console.WriteLine("{0}", reader.GetName(0));
while (reader.Read())
{
orders.Add (reader.GetInt32(0));
Console.WriteLine("{0}", orders[orders.Count-1]);
}
reader.Close();
Затем запросим (и запомним в коллекции idQuant) пары (продукт, количество), которые соответствуют индексам заказов, найденных на первом шаге. Обратите внимание на условный оператор внутри цикла чтения.
cmd = new SqlCommand(
"SELECT ProductID, Quantity From [Order Details] WHERE OrderID=@OrderID", сn);
par = cmd.Parameters.Add (new SqlParameter ("@OrderID", SqlDbType.Int));
SortedList idQuant = new SortedList();
foreach (int orderID in orders)
{
par.Value = orderID;
reader = cmd.ExecuteReader();
Console.WriteLine("\nOrder = {0}\nProductID Quantity", orderID);
while (reader.Read())
{
int pID = reader.GetInt32(0),
q = reader.GetInt16(1);
if (idQuant.Contains(pID))
idQuant[pID] = (int)idQuant[pID] + q;
else
idQuant.Add (pID, q);
Console.WriteLine("{0,-10}{1}", pID, q);
}
reader.Close();
}
На последнем шаге алгоритма получим пары (индекс продукта, продукт). Здесь используются результаты второго шага. Вывод в удобном для нас формате (тройки объектов) производим с помощью данных двух последних шагов. Алгоритм показывает, что одни и те же объекты ADO.NET можно перенастраивать и использовать повторно при вызове метода ExecuteReader.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.