Лекция ASP 8: ASP и база данных (3)
Автор:Eve Cole
Время обновления:2009-05-30 19:55:00
В последних двух лекциях мы объяснили основы использования баз данных в ASP. Сегодня мы представим несколько очень практичных технологий.
1. Технология пейджинга Мы представили, как получать данные и выводить их в браузер. Для небольшого объема данных такая простая обработка вывода вполне приемлема. Однако, если объем данных большой, с сотнями или даже тысячами элементов. , выдать клиенту столько данных за один раз нереально. Во-первых, страница очень долго тянется сверху вниз. Во-вторых, клиент слишком долго ждет. В-третьих, слишком большая нагрузка на сервер. Так что очень нужно брать постраничный вывод.
Требование: вывести данные из таблицы «Продукт» файла Northwind.mdb в браузер и отобразить по 10 элементов на каждой странице.
Возьмем в качестве примера wuf60.asp. Этот код все еще немного сложен. Вам нужно больше прочитать и испытать его. AdoAccess.asp упоминался в лекции.
Примечание. Эта процедура включает в себя хорошие моменты из некоторых книг и настоящим заявляет.
<%@ LANGUAGE="VBSCRIPT" %>
<!--#include file="AdoAccess.asp"-->
<!--#include file="adovbs.inc"-->
<%
Dim RecordPerPage, absPageNum, TotalPages, absRecordNum, rsTest, StrSQL
'absPageNum — Какая страница является текущей?
'TotalPages - Общее количество страниц.
'absRecordNum — порядковый номер записи на текущей странице, например 1-10.
RecordPerPage = 10 'Количество записей, отображаемых на странице
' Получаем текущий номер страницы выходных данных
Если Request.ServerVariables("CONTENT_LENGTH") = 0 Тогда
'Если данные, отправленные формой, не получены (например, при первой загрузке страницы), они будут отображаться со страницы 1.
абсПажеНум = 1
Еще
'Получаем номер страницы при нажатии кнопки
absPageNum = CInt(Запрос.Форма("PressPageNum"))
'Если вы нажмете предыдущую страницу, номер страницы будет -1, если вы нажмете следующую страницу, номер страницы +1
Если Request.Form("Отправить") = "Предыдущая страница" Тогда
absPageNum = absPageNum - 1
ElseIf Request.Form("Отправить") = "Следующая страница" Тогда
absPageNum = absPageNum + 1
Конец, если
Конец, если
'Создаем объект набора записей
Установите rsTest = Server.CreateObject("ADODB.Recordset")
rsTest.CursorLocation = adUseClient 'Этот параметр может снизить нагрузку на базу данных
rsTest.CursorType = adOpenStatic 'Курсор должен перемещаться вперед и назад, и его нельзя установить только вперед.
rsTest.CacheSize = RecordPerPage 'Установка этого параметра улучшит производительность
StrSQL = "ВЫБРАТЬ * ИЗ заказа продукта по идентификатору продукта"
rsTest.Open StrSQL, Cnn, , , adCmdText
rsTest.PageSize = RecordPerPage 'Установите количество записей на странице
Если нет(rsTest.EOF), то
rsTest.AbsolutePage = absPageNum
Конец, если
TotalPages = rsTest.PageCount
%>
<% 'Следующая часть выводит данные текущей страницы в браузер%>
<Html><Боби>
<таблица colspan=8 cellpadding=5 border=0>
<тр>
<td align=CENTER bgcolor="#800000" width="109"> <font style="ARIAL NARROW" color="#ffffff" size="2">Цена за единицу</font></td>
<td align=CENTER width=459 bgcolor="#800000"> <font style="ARIAL NARROW" color="#ffffff" size="2">Название продукта</font></td>
</tr>
<% 'Используйте цикл для вывода 10 фрагментов данных на текущей странице
Для absRecordNum = от 1 до rsTest.PageSize
%>
<тр>
<td bgcolor="f7efde" align=CENTER> <font style="ARIAL NARROW" size="2"><%= rsTest("цена за единицу")%></font></td>
<td bgcolor="f7efde" align=CENTER> <font style="ARIAL NARROW" size="2"><%= rsTest("Название продукта")%></font></td>
</tr>
<%
rsTest.MoveNext
Если rsTest.EOF Тогда
Exit For ' Если достигнут конец записи, выход - если последняя страница данных не заполнена.
Конец, если
Следующий
rsTest.Close : Cnn.Close
Установить rsTest = Ничего: Установить Cnn = Ничего
%>
</таблица>
<% 'Нижняя часть — две кнопки «Предыдущая страница» «Следующая страница» %>
<Form Action = "<%= Request.ServerVariables("SCRIPT_NAME") %>" Method="Post">
<Input Type="Hidden" Name="PressPageNum" Value="<%= absPageNum%>">
<%
If absPageNum > 1 then 'Если текущая страница не является первой, отобразить кнопку предыдущей страницы%>
<Input Type="Отправить" Name="Отправить" Value="Предыдущая страница">
<% Конец Если
If absPageNum <> TotalPages then 'Если текущая страница не последняя, отобразить кнопку следующей страницы%>
<Input Type="Отправить" Name="Отправить" Value="Следующая страница">
<% Конец Если %>
</Форма>
<P><Center> [Page<font color="#CC0033"><%= absPageNum %></font>,
Всего<font color="#CC0033"><%= Всего страниц %></font> страниц] </Center></P>
</BODY></HTML>
анализировать:
1. Некоторые полезные свойства объекта Recordset:
l rsTest.CursorLocation = adUseClient: это предложение также можно опустить, но это позволит снизить нагрузку на базу данных;
l rsTest.CacheSize = RecordPerPage: атрибут CacheSize используется для определения того, какой объем данных клиент получает от сервера базы данных каждый раз;
l rsTest.PageSize: атрибут PageSize используется для установки количества записей на каждой странице;
l rsTest.AbsolutePage: свойство AbsolutePage задает абсолютное количество страниц текущих данных в объекте Recordset;
l rsTest.PageCount: свойство PageCount используется для получения общего количества страниц в наборе записей.
2. В этом примере формы используется скрытое поле PressPageNum для передачи страницы при нажатии кнопки.
2. Обработка ошибок. В ходе выполнения кода могут возникать ошибки по разным причинам, например: проблемы с самим кодом, отключение сети и т. д., поэтому очень важно настроить в программе захват и обработку ошибок. В ASP мы можем получить информацию об ошибке или предупреждении, возникающую при выполнении кода через сбор данных об ошибках объекта Connection. Метод использования следующий:
1. Используйте его непосредственно на объекте Connection:
Установить Errs = Cnn.Errors
или
Cnn.Ошибки
2. После создания объекта Recordset или объекта Command используйте объект Connection через его свойство ActiveConnection:
Установите Errs = rsTest.ActiveConnection.Errors
или
rsTest.ActiveConnection.Errors
Это звучит слишком грубо, поэтому давайте приведем пример: wuf61.asp.
<%@ LANGUAGE="VBSCRIPT" %>
<% Опция явная %>
<!--#include file="adovbs.inc"-->
<%
Ответ.Истекает = 0
'Следующее предложение гарантирует: даже если сценарий обнаружит ошибку, он продолжит выполнение следующего предложения.
При ошибке Возобновить Далее
Дим Cnn, rsTest, Errs, I
Установить Cnn = Server.CreateObject("ADODB.Connection")
'CommandTimeout - максимальное время ожидания подключения к базе данных, по умолчанию 15 секунд
Cnn.CommandTimeout = 5
«Вы можете обнаружить ошибки в следующих трех ситуациях — на примере SQL Server.
'1 - полностью верно; 2 - исходная база данных не установлена 3 - неправильное имя базы данных pvbs;
Cnn.Open "Provider=sqloledb; Идентификатор пользователя=sa; Пароль=; Начальный каталог=pubs; Источник данных=ICBCZJP"
'Cnn.Open "Provider=sqloledb; Идентификатор пользователя=sa; Пароль=; Начальный каталог=; Источник данных=ICBCZJP"
'Cnn.Open "Provider=sqloledb; Идентификатор пользователя=sa; Пароль=; Начальный каталог=pvbs; Источник данных=ICBCZJP"
Для I = 0 Для Cnn.Errors.Count - 1
'Атрибут Source указывает источник ошибки
Response.Write "[ " & Cnn.Errors(I).Source & " ] "
'Атрибут описания указывает причину или описание ошибки.
Response.Write Cnn.Errors(I).Description & "<br>"
Следующий
Если Cnn.Errors.Count > 0 Тогда
Response.Write «Произошло при подключении» & Cnn.Errors.Count & «ошибки» & «<br>»
Конец, если
Установите rsTest = Server.CreateObject("ADODB.Recordset")
rsTest.Open "задания", Cnn, adOpenForwardOnly, adLockReadOnly, adCmdTable
Если rsTest.ActiveConnection.Errors.Count > 0 Тогда
Set Session("Errs") = rsTest.ActiveConnection.Errors
Response.Redirect "ErrorHandle.asp"
Конец, если
Cnn.Закрыть
Установить rsTest = Ничего: Установить Cnn = Ничего
%>
Код ErrorHandle.asp:
<%
Дим я
Для I = 0 To Session("Ошибки").Count - 1
Response.Write "[ " & Session("Errs")(I).Source & " ] "
Response.Write Session("Errs")(I).Description & "<br>"
Следующий
%>
анализировать:
В этом случае могла возникнуть ошибка при подключении, либо соединение было корректным, но при использовании объекта Recordset произошла ошибка.
Кроме того, в следующем фрагменте кода коллекция ошибок помещается в объект сеанса, чтобы ее можно было вызывать между страницами (при обнаружении ошибки перейдите на страницу обработки ошибок ErrorHandle.asp).
Фактически, вы также можете назначить объект Recordset объекту Session, чтобы реализовать вызов набора записей между страницами.
3. Концепция использования транзакций очень проста и важна. Чтобы проиллюстрировать ее использование, давайте сначала предположим следующую ситуацию: например, в электронной коммерции при проведении валютных переводов в Интернете необходимо вычесть определенную сумму из суммы. сумму и добавьте ее эквивалентную сумму на другой счет. Какое бы из обновлений не состоялось, это приведет к разбалансировке баланса счета (либо здесь есть удержание, а там нет увеличения, либо здесь нет удержания, а там есть увеличение) . Если вы используете транзакцию для внесения этих изменений, вы гарантируете, что сможете выбрать только внесение всех изменений или отсутствие изменений (либо полностью правильное, либо полностью отмененное).
Транзакции принадлежат объекту Connection, который имеет три метода, связанных с транзакциями:
l BeginTrans запускает новую транзакцию.
l CommitTrans сохраняет все изменения и завершает текущую транзакцию.
l RollbackTrans отменяет любые изменения, внесенные в текущую транзакцию, и завершает транзакцию, часто называемую «откатом».
Мы могли бы также рассмотреть пример wuf62.asp.
<%@ LANGUAGE="VBSCRIPT" %>
<% Опция явная %>
<!--#include file="adovbs.inc"-->
<%
Ответ.Истекает = 0
При ошибке Возобновить Далее
ДимКнн, СтрSQL, рстест
Установить Cnn = Server.CreateObject("ADODB.Connection")
Cnn.Open "Provider=sqloledb; Идентификатор пользователя=sa; Пароль=; Начальный каталог=pubs; Источник данных=ICBCZJP"
'Начать транзакцию
Cnn.BeginTrans
StrSQL = "Вставить значения jobs(job_desc, min_lvl, max_lvl)('Finance',16,86)"
Cnn.Execute StrSQL
«Первое предложение ниже неверно, второе предложение верно.
StrSQL = «Обновить jobs_err SET job_desc = 'Транзакция', где job_id = 14»
'StrSQL = "Обновление заданий SET job_desc = 'Транзакция', где job_id = 14"
Cnn.Execute StrSQL
Если Cnn.Errors.Count > 0 Тогда
Ответ.Написать "Произошла ошибка, система восстанавливает состояние на начало транзакции, ни новых дополнений, ни изменений производиться не будет" & "<br>"
Cnn.RollbackTrans
Еще
Ответ. Напишите «Нет ошибок, сохраните изменения в базе данных, добавьте новый фрагмент данных, измените фрагмент данных» & «<br>»
Cnn.CommitTrans
Конец, если
Set rsTest = Cnn.Execute("Выбрать * Из заданий, где job_id>=14")
Пока это не rsTest.EOF
Response.Write rstest(0) & rstest(1) & rstest(2) & rstest(3) & "<br>"
rsTest.MoveNext
Венд
'Этот пример предназначен только для тестирования, поэтому восстановите исходные данные базы данных
Cnn.Execute «Обновление заданий SET job_desc = 'Designer', где job_id = 14»
Cnn.Execute «УДАЛИТЬ задания, где job_id > 14»
Cnn.Close: Установить Cnn = Ничего
%>
В этом примере операции «Вставка» и «Обновление» либо выполняются одновременно, либо ни одна из них не происходит. Не будет ситуации, когда часть данных добавляется, но изменение не происходит из-за ошибки оператора. Использование транзакций — очень хорошая привычка при программировании баз данных.
4. Обработка нескольких наборов записей. Иногда нам необходимо получить данные из двух таблиц одновременно. Если они возвращаются в одном операторе SQL, можно сократить передачу по сети и повысить эффективность работы.
Возьмем в качестве примера wuf64.asp. В этом примере также объясняется, как использовать цикл для вывода значений полей (ранее мы использовали для вывода глупые методы, такие как «rsTest(0) & rsTest(1) &...»). Если полей всего два-три, то этот метод, очевидно, более лаконичный), если вы в данный момент не можете в нем разобраться, скачайте более простой wuf63.asp, помните! .
<%@ LANGUAGE="VBSCRIPT" %>
<%
Опция явная
Ответ.Истекает = 0
Дим Cnn, StrSQL, rsTest, я
Установить Cnn = Server.CreateObject("ADODB.Connection")
Cnn.Open "Provider=sqloledb; Идентификатор пользователя=sa; Пароль=; Начальный каталог=pubs; Источник данных=ICBCZJP"
Установите rsTest = Server.CreateObject("ADODB.Recordset")
'Получить несколько наборов записей
StrSQL = "Выберите COUNT(*) AS 'Количество сотрудников' От сотрудника; Выберите * Из должностей"
rsTest.Open StrSQL, Cnn ', , ,adCmdText
Пока не rsTest — ничего
Response.Write "<Граница таблицы = 2><tr>"
'rsTest.Fields.Count — количество полей в наборе записей.
Для I = 0 Для rsTest.Fields.Count - 1
'rsTest(I).Name - имя поля I.
Response.Write "<td>" & rsTest(I).Name & "</td>"
Следующий
Ответ. Напишите "</tr>"
Пока это не rsTest.EOF
Ответ. Напишите "<tr>"
'Используем цикл для вывода значения каждого поля
Для I = 0 Для rsTest.Fields.Count - 1
Response.Write "<td>" & rsTest(I) & "</td>"
Следующий
Ответ. Напишите "</tr>"
rsTest.MoveNext
Венд
'Читать следующий объект набора записей
Установите rsTest = rsTest.NextRecordset
Венд
Cnn.Закрыть
Установить rsTest = Ничего: Установить Cnn = Ничего
%>
Примечание. База данных SQL Server поддерживает несколько наборов записей, а база данных Access — нет.
5. Закройте соединение как можно раньше, чтобы освободить ресурсы.
В предыдущих примерах соединение было закрыто последним. Однако объект Connection занимает ресурсы. Фактически, согласно методу, предоставленному wuf65.asp ниже, соединение можно закрыть раньше.
<% @LANGUAGE = VBScript %>
<!--#include file="AdoAccess.asp"-->
<!--#include file="adovbs.inc"-->
<% 'wuf65.asp
Дим StrSQL, rsTest
StrSQL = "Выбрать * От отправителя"
Установите rsTest = server.CreateObject("ADODB.Recordset")
'Вы должны использовать клиентский курсор, иначе он не будет работать
rsTest.CursorLocation = adUseClient
rsTest.Open StrSQL,Cnn,,,adCmdText
'Удалить зависимость набора записей от объекта Connection
Установите rsTest.ActiveConnection = Ничего
'Закройте соединение как можно раньше
Cnn.close: Установить Cnn = Ничего
Делайте, пока не rsTest.EOF
Response.Write rsTest(0) & " " & rsTest(1) & " " & rsTest(2) & " " & "<BR>"
rsTest.MoveNext
Петля
Установить rsTest = Ничего
%>