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
absPageNum = 1
อื่น
'รับหมายเลขหน้าเมื่อกดปุ่ม
absPageNum = CInt(Request.Form("PressPageNum"))
'ถ้ากดหน้าก่อนหน้าเลขหน้าเป็น -1 ถ้ากดหน้าถัดไปเลขหน้า +1
ถ้า Request.Form("Submit") = "Previous page" จากนั้น
absPageNum = absPageNum - 1
ElseIf Request.Form("Submit") = "หน้าถัดไป" จากนั้น
absPageNum = absPageNum + 1
สิ้นสุดถ้า
สิ้นสุดถ้า
'สร้างวัตถุชุดระเบียน
ตั้งค่า rsTest = Server.CreateObject("ADODB.Recordset")
rsTest.CursorLocation = adUseClient 'การตั้งค่านี้สามารถลดภาระฐานข้อมูลได้
rsTest.CursorType = adOpenStatic 'เคอร์เซอร์จำเป็นต้องเลื่อนไปข้างหน้าและข้างหลัง และไม่สามารถตั้งค่าให้ส่งต่อเท่านั้น
rsTest.CacheSize = RecordPerPage 'การตั้งค่าตัวเลือกนี้จะปรับปรุงประสิทธิภาพ'
StrSQL = "เลือก * จาก productOrder ตามรหัสผลิตภัณฑ์"
rsTest.เปิด StrSQL, Cnn, , , adCmdText
rsTest.PageSize = RecordPerPage 'กำหนดจำนวนบันทึกต่อหน้า
ถ้าไม่ใช่(rsTest.EOF) งั้น
rsTest.AbsolutePage = absPageNum
สิ้นสุดถ้า
TotalPages = rsTest.PageCount
-
<% 'ส่วนต่อไปนี้จะแสดงข้อมูลของหน้าปัจจุบันไปยังเบราว์เซอร์%>
<Html><โบบี้>
<ตาราง colspan=8 เซลล์แพดดิ้ง=5 เส้นขอบ=0>
<tr>
<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
-
<tr>
<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 แล้ว
ออกสำหรับ ' หากถึงจุดสิ้นสุดของบันทึก ให้ออก - หากหน้าสุดท้ายของข้อมูลไม่เต็ม
สิ้นสุดถ้า
ต่อไป
rsTest.Close : Cnn.ปิด
Set rsTest = Nothing : Set Cnn = Nothing
-
</ตาราง>
<% 'ส่วนล่างคือปุ่มสองปุ่ม "ก่อนหน้า" "หน้าถัดไป" %>
<การกระทำของฟอร์ม = "<%= Request.ServerVariables("SCRIPT_NAME") %>" Method="Post">
<Input Type="Hidden" Name="PressPageNum" Value="<%= absPageNum%>">
-
ถ้า absPageNum > 1 จากนั้น 'หากหน้าปัจจุบันไม่ใช่หน้าแรก ให้แสดงปุ่มหน้าก่อนหน้า%>
<Input Type="Submit" Name="Submit" Value="Previous Page">
<% สิ้นสุดถ้า
ถ้า absPageNum <> TotalPages จากนั้น 'หากหน้าปัจจุบันไม่ใช่หน้าสุดท้าย ให้แสดงปุ่มหน้าถัดไป%>
<Input Type="Submit" Name="Submit" Value="Next page">
<% สิ้นสุดถ้า %>
</แบบฟอร์ม>
<P><Center> [หน้า<font color="#CC0033"><%= absPageNum %></font>,
รวม<font color="#CC0033"><%= TotalPages %></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 เราสามารถรับข้อผิดพลาดหรือข้อมูลคำเตือนที่เกิดขึ้นเมื่อรหัสกำลังทำงานผ่านการรวบรวมข้อมูลข้อผิดพลาดของวัตถุการเชื่อมต่อ วิธีการใช้งานจะเป็นดังนี้:
1. ใช้มันโดยตรงบนวัตถุการเชื่อมต่อ:
ตั้งค่าข้อผิดพลาด = Cnn.Errors
หรือ
Cnn.ข้อผิดพลาด
2. หลังจากสร้างวัตถุ Recordset หรือวัตถุ Command ให้ใช้วัตถุการเชื่อมต่อผ่านคุณสมบัติ ActiveConnection:
ตั้งค่าข้อผิดพลาด = rsTest.ActiveConnection.Errors
หรือ
rsTest.ActiveConnection.ข้อผิดพลาด
มันฟังดูหยาบคายเกินกว่าจะพูด ดังนั้นมายกตัวอย่าง: wuf61.asp
<%@ LANGUAGE="VBSCRIPT" %>
<% ตัวเลือกที่ชัดเจน %>
<!--#include file="adovbs.inc"-->
-
การตอบกลับหมดอายุ = 0
'ประโยคต่อไปนี้รับประกัน: แม้ว่าสคริปต์จะพบข้อผิดพลาด สคริปต์จะยังคงดำเนินการประโยคถัดไป
เมื่อเกิดข้อผิดพลาด ดำเนินการต่อต่อไป
Dim Cnn, rsTest, ข้อผิดพลาด, I
ตั้งค่า Cnn = Server.CreateObject("ADODB.Connection")
'CommandTimeout - เวลารอสูงสุดสำหรับการเชื่อมต่อกับฐานข้อมูล ค่าเริ่มต้นคือ 15 วินาที
Cnn.CommandTimeout = 5
'คุณสามารถตรวจพบข้อผิดพลาดได้ในสามสถานการณ์ต่อไปนี้ - โดยใช้ SQL Server เป็นตัวอย่าง
'1 - ถูกต้องสมบูรณ์ 2 - ไม่ได้ตั้งค่าฐานข้อมูลเริ่มต้น 3 - ชื่อฐานข้อมูล pvbs ไม่ถูกต้อง
Cnn.Open "Provider=sqloledb; User ID=sa; Password=; Initial Catalog=pubs; Data Source=ICBCZJP"
'Cnn.Open "ผู้ให้บริการ = sqloledb; ID ผู้ใช้ = sa; รหัสผ่าน =; แค็ตตาล็อกเริ่มต้น =; แหล่งข้อมูล = ICBCZJP"
'Cnn.Open "ผู้ให้บริการ = sqloledb; ID ผู้ใช้ = sa; รหัสผ่าน =; แค็ตตาล็อกเริ่มต้น = pvbs; แหล่งข้อมูล = ICBCZJP"
สำหรับ I = 0 ถึง Cnn.Errors.Count - 1
'แอตทริบิวต์แหล่งที่มาระบุแหล่งที่มาของข้อผิดพลาด
Response.Write "[ " & Cnn.Errors(I).Source & " ] "
'แอตทริบิวต์คำอธิบายระบุเหตุผลหรือคำอธิบายของข้อผิดพลาด
Response.Write Cnn.Errors(I)คำอธิบาย & "<br>"
ต่อไป
ถ้า Cnn.Errors.Count > 0 แล้ว
การตอบสนองเขียน "เกิดขึ้นขณะเชื่อมต่อ" & Cnn.Errors.Count & " ข้อผิดพลาด" & "<br>"
สิ้นสุดถ้า
ตั้งค่า rsTest = Server.CreateObject("ADODB.Recordset")
rsTest.Open "งาน", Cnn, adOpenForwardOnly, adLockReadOnly, adCmdTable
ถ้า rsTest.ActiveConnection.Errors.Count > 0 แล้ว
ตั้งค่าเซสชัน ("ข้อผิดพลาด") = rsTest.ActiveConnection.Errors
Response.Redirect "ErrorHandle.asp"
สิ้นสุดถ้า
ซีเอ็น.ปิด
Set rsTest = Nothing : Set Cnn = Nothing
-
รหัส ErrorHandle.asp:
-
ดิม ไอ
สำหรับ I = 0 ถึงเซสชัน ("ข้อผิดพลาด") นับ - 1
การตอบกลับเขียน "[ " & เซสชัน ("ข้อผิดพลาด")(I). แหล่งที่มา & " ] "
Response.Write Session("ข้อผิดพลาด")(I).Description & "<br>"
ต่อไป
-
วิเคราะห์:
ในกรณีนี้ อาจเกิดข้อผิดพลาดขณะเชื่อมต่อ หรือการเชื่อมต่ออาจถูกต้อง แต่มีข้อผิดพลาดเกิดขึ้นขณะใช้วัตถุ Recordset
นอกจากนี้ ในโค้ดต่อไปนี้ การรวบรวมข้อผิดพลาดจะถูกใส่ลงในวัตถุเซสชันเพื่อให้สามารถเรียกระหว่างเพจต่างๆ ได้ (เมื่อพบข้อผิดพลาด ให้เปลี่ยนไปที่หน้าการจัดการข้อผิดพลาด ErrorHandle.asp)
ในความเป็นจริง คุณยังสามารถกำหนดออบเจ็กต์ Recordset ให้กับออบเจ็กต์เซสชันเพื่อใช้การเรียกชุดระเบียนระหว่างเพจได้
3. แนวคิดของการใช้ธุรกรรมนั้นเรียบง่ายและสำคัญมาก เพื่ออธิบายการใช้งาน ให้เราสมมติสถานการณ์ต่อไปนี้ก่อน: ตัวอย่างเช่น ในอีคอมเมิร์ซ เมื่อดำเนินการโอนเงินออนไลน์ จะต้องลบจำนวนเงินจำนวนหนึ่งออกจาก บัญชีและเพิ่มจำนวนเงินที่เทียบเท่ากับบัญชีอื่น ไม่ว่าการอัปเดตตัวใดตัวหนึ่งจะล้มเหลว จะนำไปสู่ความไม่สมดุลในยอดคงเหลือของบัญชี (มีการหักเงินที่นี่ แต่ไม่มีการเพิ่มขึ้นที่นั่น หรือไม่มีการหักเงินที่นี่ แต่มีการเพิ่มขึ้นที่นั่น) . หากคุณใช้ธุรกรรมเพื่อทำการเปลี่ยนแปลงเหล่านี้ คุณมั่นใจได้ว่าคุณสามารถเลือกที่จะทำการเปลี่ยนแปลงทั้งหมดหรือไม่ทำการเปลี่ยนแปลงเท่านั้น (ถูกต้องทั้งหมดหรือยกเลิกทั้งหมด)
ธุรกรรมเป็นของวัตถุการเชื่อมต่อซึ่งมีวิธีการที่เกี่ยวข้องกับธุรกรรมสามวิธี:
l BeginTrans เริ่มธุรกรรมใหม่
l CommitTrans บันทึกการเปลี่ยนแปลงทั้งหมดและสิ้นสุดธุรกรรมปัจจุบัน
l RollbackTrans ยกเลิกการเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นในธุรกรรมปัจจุบันและสิ้นสุดธุรกรรม ซึ่งมักเรียกว่า "ย้อนกลับ"
เราอาจดูตัวอย่าง wuf62.asp เช่นกัน
<%@ LANGUAGE="VBSCRIPT" %>
<% ตัวเลือกที่ชัดเจน %>
<!--#include file="adovbs.inc"-->
-
การตอบกลับหมดอายุ = 0
เมื่อเกิดข้อผิดพลาด ดำเนินการต่อต่อไป
DimCnn, StrSQL, rsTest
ตั้งค่า Cnn = Server.CreateObject("ADODB.Connection")
Cnn.Open "Provider=sqloledb; User ID=sa; Password=; Initial Catalog=pubs; Data Source=ICBCZJP"
'เริ่มต้นการทำธุรกรรม
Cnn.BeginTrans
StrSQL = "แทรกงาน (job_desc, min_lvl, max_lvl) ค่า ('การเงิน',16,86)"
Cnn.ดำเนินการ StrSQL
'ประโยคแรกด้านล่างผิด ประโยคที่สองถูกต้อง'
StrSQL = "อัปเดต jobs_err SET job_desc = 'ธุรกรรม' โดยที่ job_id = 14"
'StrSQL = "อัปเดตงาน SET job_desc = 'ธุรกรรม' โดยที่ job_id = 14"
Cnn.ดำเนินการ StrSQL
ถ้า Cnn.Errors.Count > 0 แล้ว
ตอบกลับเขียน "เกิดข้อผิดพลาด ระบบกู้คืนสถานะเมื่อเริ่มต้นธุรกรรม จะไม่เพิ่มหรือแก้ไขใหม่" & "<br>"
Cnn.RollbackTrans
อื่น
Response.Write "ไม่มีข้อผิดพลาด บันทึกการเปลี่ยนแปลงฐานข้อมูล เพิ่มข้อมูลใหม่ แก้ไขข้อมูล" & "<br>"
Cnn.CommitTrans
สิ้นสุดถ้า
ตั้งค่า rsTest = Cnn.Execute("เลือก * จากงานที่ job_id>=14")
ในขณะที่ไม่ใช่ rsTest.EOF
การตอบสนองเขียน rstest(0) & rstest(1) & rstest(2) & rstest(3) & "<br>"
rsTest.MoveNext
เวนด์
'ตัวอย่างนี้ใช้สำหรับการทดสอบเท่านั้น ดังนั้นให้คืนค่าข้อมูลต้นฉบับของฐานข้อมูล
Cnn.Execute "อัปเดตงาน SET job_desc = 'ผู้ออกแบบ' โดยที่ job_id = 14"
Cnn.Execute "ลบงานโดยที่ job_id > 14"
Cnn.Close: ตั้งค่า Cnn = ไม่มีเลย
-
ในตัวอย่างนี้ การแทรกและการอัปเดตเกิดขึ้นพร้อมกันหรือไม่เกิดขึ้น จะไม่มีสถานการณ์ที่มีการเพิ่มข้อมูลชิ้นหนึ่ง แต่การแก้ไขจะไม่เกิดขึ้นเนื่องจากข้อผิดพลาดของคำสั่ง การใช้ธุรกรรมเป็นนิสัยที่ดีมากเมื่อเขียนโปรแกรมฐานข้อมูล
4. การประมวลผลชุดระเบียนหลายชุด บางครั้งเราจำเป็นต้องได้รับข้อมูลจากสองตารางพร้อมกัน หากส่งคืนในคำสั่ง SQL เดียว การส่งข้อมูลเครือข่ายอาจลดลงและปรับปรุงประสิทธิภาพการทำงาน
ยกตัวอย่าง wuf64.asp ตัวอย่างนี้ยังอธิบายวิธีใช้ลูปเพื่อส่งออกค่าฟิลด์ (เมื่อก่อนเราใช้วิธีโง่ๆ เช่น "rsTest(0) & rsTest(1) &..." เพื่อส่งออก . หากมีเพียงสองหรือสามฟิลด์ วิธีการนี้จะกระชับมากขึ้น) หากคุณไม่เข้าใจในขณะนี้ โปรดดาวน์โหลด wuf63.asp ที่ง่ายกว่านี้ จำไว้! -
<%@ LANGUAGE="VBSCRIPT" %>
-
ตัวเลือกที่ชัดเจน
การตอบกลับหมดอายุ = 0
Dim Cnn, StrSQL, rsTest, I
ตั้งค่า Cnn = Server.CreateObject("ADODB.Connection")
Cnn.Open "Provider=sqloledb; User ID=sa; Password=; Initial Catalog=pubs; Data Source=ICBCZJP"
ตั้งค่า rsTest = Server.CreateObject("ADODB.Recordset")
'ดึงชุดระเบียนหลายชุด
StrSQL = "เลือก COUNT(*) AS 'จำนวนพนักงาน' จากพนักงาน; เลือก * จากงาน"
rsTest.เปิด StrSQL, Cnn ', , ,adCmdText
ในขณะที่ Not rsTest นั้นไม่มีอะไรเลย
Response.Write "<เส้นขอบตาราง = 2><tr>"
'rsTest.Fields.Count - จำนวนฟิลด์ในชุดระเบียน
สำหรับ I = 0 ถึง rsTest.Fields.Count - 1
'rsTest(I).Name - ชื่อฟิลด์ของฟิลด์ I
การตอบกลับเขียน "<td>" & rsTest(I).ชื่อ & "</td>"
ต่อไป
ตอบกลับเขียน "</tr>"
ในขณะที่ไม่ใช่ rsTest.EOF
ตอบกลับเขียน "<tr>"
'ใช้การวนซ้ำเพื่อส่งออกค่าของแต่ละฟิลด์
สำหรับ I = 0 ถึง rsTest.Fields.Count - 1
การตอบกลับเขียน "<td>" & rsTest(I) & "</td>"
ต่อไป
ตอบกลับเขียน "</tr>"
rsTest.MoveNext
เวนด์
'อ่านวัตถุชุดระเบียนถัดไป
ตั้งค่า rsTest = rsTest.NextRecordset
เวนด์
ซีเอ็น.ปิด
ตั้งค่า rsTest = ไม่มีเลย: ตั้งค่า Cnn = ไม่มีเลย
-
หมายเหตุ: ฐานข้อมูล SQL Server รองรับชุดระเบียนหลายชุด แต่ฐานข้อมูล Access ไม่รองรับ
5. ปิดการเชื่อมต่อโดยเร็วที่สุดเพื่อปล่อยทรัพยากร
ในตัวอย่างก่อนหน้านี้ การเชื่อมต่อถูกปิดในลำดับสุดท้าย อย่างไรก็ตาม การเชื่อมต่อสามารถปิดได้เร็วกว่าปกติตามวิธีที่ 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.เปิด StrSQL,Cnn,,,adCmdText
'เอาการพึ่งพาของชุดระเบียนบนวัตถุการเชื่อมต่อออก
ตั้งค่า rsTest.ActiveConnection = ไม่มีเลย
'ปิดการเชื่อมต่อโดยเร็วที่สุด
Cnn.close: ตั้งค่า Cnn = ไม่มีเลย
ทำในขณะที่ไม่ใช่ rsTest.EOF
การตอบสนองเขียน rsTest(0) & " " & rsTest(1) & " " & rsTest(2) & " " & "<BR>"
rsTest.MoveNext
วนซ้ำ
ตั้งค่า rsTest = ไม่มีเลย
-