เขียนบทความเกี่ยวกับ VB + ฐานข้อมูลมาก็ไม่ใช่น้อยแล้ว แปลกใจที่ไม่มีใครมาถามเกี่ยวกับ Error ตัวนี้สักทีเลย 55555+ ... แม้แต่ในบทความบางตัวผมเองก็มีเจตนาวาง Bug ไว้ให้ก็ยังไม่มีใครเห็นกระนั้นเชียวหรือครับพี่น้อง ... ลองไปดูในบทความเรื่อง การอ่านข้อมูลแบบ Text File เข้าสู่ MS Access ด้วย MS Visual Basic 6.0 ภาค 2
' แบบที่ 1 - For ... Next
' นั่นคือ For i = 29 To 1 ลดค่าลงทีละ 1 ... จาก 29, 28, 27, ... 1
For i = Len(txtFilePath) To 1 Step -1
If Mid$(txtFilePath, i, 1) = "\" Then
' นับไปจากทางซ้ายมือตาม i = 17 ก็จะได้ C:\TestVB\Sample\
strPath = Left$(txtFilePath, i)
' เด้งออกจาก For Loop ไปเลย ... หมดหน้าที่แล้ว ... 55555+
Exit For
End If
Next
จะสังเกตได้เลยว่า เมื่อผมบังคับให้ตัวแปรทุกๆตัวต้องการทำการประกาศชื่อแซ่ของมันก่อนการใช้งานด้วย Option Explicit แต่ทำไมตัวแปร i นั้นผมไม่ได้ประกาศเอาไว้เลย ... แต่ทว่าโปรแกรมกลับทำงานได้เฉยเลย ... เหอๆๆๆๆ ก่อนอื่นต้องมาว่าเรื่อง ของ CursorType กับ LockType กันก่อนครับ
RS.Open SQLStmt, Conn, adOpenForwardOnly, adLockReadOnly, adCmdText จะใช้ในกรณีของการอ่านข้อมูล (Read Only) เข้ามาเท่านั้น เพื่อเร่งความเร็วในการเข้าถึงข้อมูล ที่ใช้สำหรับการค้นหา หรือ การแสดงผล
RS.Open Statement, Conn, adOpenKeyset, adLockOptimistic, adCmdText ส่วนแบบนี้ใช้ใน กรณีของการเขียนข้อมูล (AddNew/Insert หรือ Update) หากไปลองค้นหาจากบทความของผม จะเห็นเลยว่าบางกรณีมันไม่ได้เป็นไปตามนั้นหรอก ... คำเฉลยอยู่ด้านล่างครับพี่น้อง
เอ้าทีนี้มาพิจารณาการเกิด Run-time error '3705' สาเหตุสำคัญคือ การเปิดการเชื่อมต่อของตารางข้อมูลค้างเอาไว้อยู่ ไม่ยอมปิดด้วยคำสั่ง
RS.Close หรือ Set RS = Nothing
หรือก่อนที่จะใช้งาน RecordSet ก็ใช้คำสั่ง Set RS = New ADODB.Recordset ซึ่งก็เสมือนหนึ่งตัดขาดการเชื่อมต่อเดิมออกไปเลย
ที่ต้องมากล่าวถึงที่มาที่ไปของมันนี่ ผมเชื่อว่าหลายคนอาจจะยังไม่เคยเจอเหตุการณ์แบบนี้ เนื่องจากพี่น้องไปเล่น ประกาศตัวแปร Object ซ่ะเกลื่อนน่ะซิ เช่น rstEmployee, rstProduct, rstCustomer และอื่นๆอีก คือ จะใช้ตารางตัวไหนก็ประกาศตามชื่อตารางนั้นๆไป จะปิด หรือ ไม่ปิดก็แทบไม่ต้องไปสนใจมัน 55555+ ... พอมาเห็น VB Project ของผมมันทำไมมีแค่ 2 ตัว คือ RS กับ DS แบบหมุนเวียนการใช้งานอยู่แค่นี้ ก็เลยงงๆกันไป (บางทียังมี GMM Grammy มาอีก) ... ปัญหาตามที่กล่าวมานั้น เราแก้ได้ไม่ยาก ... แต่ปัญหาที่เข็มขัดสั้่น คาดไม่ถึง ก็คือ แม้ว่าเราจะปิดการเชื่อมต่อฐานข้อมูลทั้งหมดแล้วก็ตาม หรือปิดไปทั้งโปรแกรมแล้วเปิดขึ้นมาใหม่ เอ้า Restart เครื่องใหม่ด้วยน่ะ มันก็ยังเกิด Run-time error '3705': Operation is not allowed when the object is open ... งงตายเลย ไล่ Debug โค้ดตั้งนาน มันไปลืมปิดการเชื่อมต่อที่ไหนบ้าง เปลี่ยนชื่อตัวแปรใหม่ เปลี่ยนชื่อไฟล์ข้อมูลใหม่ ... ทำสารพัดอย่างก็ไม่ได้เลย ... เฮ้อ สุดท้ายก็ได้คำตอบออกมา คือ เกิดข้อผิดพลาดในระบบขึ้นมาดื้อๆด้านๆซ่ะงั้น ส่วนจะมาจากอะไรนั้นผมเองก็ขี้เกียจไปไล่ตามหามัน เอาเป็นว่าได้รับคำตอบมาจาก "เล็กนิ่ม - Microsoft" คือ ในฝั่ง Client-Side นั้นสามารถปิดการเชื่อมต่อได้อย่างสมบูรณ์ แต่ไม่สามารถปิดทางฝั่ง Server-Side ได้ จึงทำให้เกิด Error 3705 ขึ้นมาตามที่ได้กล่าวไปแล้ว แต่ทว่าเราจะไม่สามารถใช้งาน RS.CursorLocation = adUseClient ได้เลยน่ะครับ ... พี่น้อง (แล้วทางเล็กนิ่มมันจะอธิบายมาให้งงทำไม (ว่ะ) เนี่ย) การแก้ปัญหาจากทาง "เล็กนิ่ม - Microsoft"
Private Sub Command1_Click()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
cn.Open "Provider= อะไรก็ว่าไป;"
rs.Open "Select * from ตารางข้อมูล", cn, adOpenStatic, adLockBatchOptimistic
Set rs.ActiveConnection = Nothing
rs.Close
cn.Close
End Sub
กรณีที่เครื่องผมน่ะ ... ผมลองทดสอบดูแล้ว ไม่เวิร์ค ครับพี่น้อง ... ปวดกบาลหนักเข้าไปอีก (จำไม่ได้ว่าตอนนี้นหมดเบียร์แก้ปวดหัวไปกี่ขวดกัน ... 55555) ... สุดท้ายก็มั่วเอา คือ ลองเปลี่ยน CursorType กับ LockType เช่น กรณีการอ่านข้อมูลอย่างเดียว
RS.Open SQLStmt, Conn, adOpenForwardOnly, adLockOptimistic, adCmdText ... หรือ เอาแบบชัวร์ๆ
RS.Open SQLStmt, Conn, adOpenKeyset, adLockOptimistic, adCmdText ... แย้งทฤษฎีหน่อย รันผ่านครับพี่น้อง ... หลังจากนั้นก็เฝ้าๆๆๆๆสังเกตดู แล้วก็ลองมาเปลี่ยน CursorType กับ LockType ให้กลับมาอยู่ในรูปแบบที่มันควรจะเป็น ... PASS ไร้ปัญหาครับพี่น้อง สรุปได้ง่ายๆก็คือ BUG ของตัวโปรแกรม MS Visual Basic 6 เองนั่นแหละ ... ไม่ต้องไปคิดมาก ... จบโปรแกรม ปิดงาน มุ่งหน้าไปรับตังค์ 55555+
|