ข้อเสนอแนะรหัส VBA-Sync
ฉันหวังว่าจะได้รับข้อมูลบางอย่างในโมดูลคลาสที่ฉันออกแบบให้เป็นนามธรรมต้นแบบของการใช้แบบสอบถามแบบอะซิงโครนัสใน VBA cQueryable รองรับทั้งแบบสอบถามแบบซิงโครนัสและอะซิงโครนัส คุณสามารถทำบางอย่างเช่นเรียกแพ็คเกจเพื่อเติมข้อมูลตารางชั่วคราว สิ่งนี้จะทำพร้อมกันเนื่องจากคุณต้องการให้เสร็จสิ้นก่อนที่คุณจะดำเนินการค้นหาที่คุณเลือก หลังจากนั้นคุณจะดำเนินการแบบสอบถามที่เลือกในแต่ละตารางชั่วคราวแบบอะซิงโครนัส
รหัสนี้เป็นเพียงแค่สรุปฟังก์ชันการทำงานจำนวนมากในไลบรารี ADODB ฉันพยายามตั้งชื่อคุณสมบัติและวิธีการให้คล้ายกับสิ่งที่อ็อบเจ็กต์ในไลบรารีนั้นใช้หากเป็นไปได้ คุณสมบัติ connectionString ของฉันมีชื่อคล้ายกับคุณสมบัติเดียวกันในวัตถุ ADODB.Connection และเมธอด CreateParam ของฉันมีชื่อคล้ายกับเมธอด createParameter ของอ็อบเจ็กต์ ADODB.Command
ขั้นตอนใหม่บางส่วนที่ฉันได้แนะนำคือคุณสมบัติ sql สิ่งนี้เก็บเคียวรี sql ที่จะดำเนินการ (แมปนี้กับข้อความคำสั่งในอ็อบเจ็กต์คำสั่ง) อีกประการหนึ่งคือ ProcedureAfterQuery นี่คือการถือโพรซีเดอร์ชื่อที่จะเรียกโดยอ็อบเจ็กต์การเชื่อมต่อหลังจากสร้างเหตุการณ์เมื่อเคียวรีเสร็จสมบูรณ์ อื่น ๆ ได้แก่ SyncExecute และ AsyncExecute ซึ่งควรอธิบายถึงสิ่งที่พวกเขาทำในชื่อของพวกเขา
สิ่งหนึ่งที่ควรทราบเกี่ยวกับสองสิ่งนี้คือ SyncExecute เป็นฟังก์ชันในขณะที่ AsyncExecute เป็นรูทีนย่อย ฉันต้องการให้ SyncExecute ส่งคืนชุดระเบียนเมื่อเสร็จสิ้น แต่สำหรับ AsyncExecute ฉันต้องการให้เป็นส่วนย่อยที่ฉันไม่ต้องการบอกเป็นนัยว่ามันส่งคืนอะไร ฉันใช้รหัสที่คล้ายกัน (แต่ต่างกัน) เพื่อทำสิ่งนี้ ดังนั้นฉันคิดว่าฉันละเมิดหลักการ DRY ฉันสามารถรวมสองสิ่งนี้เพื่อเรียกหนึ่งกระบวนงานย่อยที่ใช้ร่วมกัน ขั้นตอนที่ใช้ร่วมกันนั้นจะซับซ้อนมากขึ้น แต่อย่างน้อยรหัสก็จะถูกแชร์ ฉันไม่มีความชอบไม่ทางใดก็ทางหนึ่ง
แม้ว่า CreateParam จะคล้ายกับเมธอด CreateParameter ของวัตถุคำสั่ง แต่ก็มีความแตกต่างสองประการ หนึ่งคือลำดับของข้อโต้แย้งแตกต่างกัน ส่วนใหญ่เป็นเพราะพารามิเตอร์ขนาดและทิศทางแสดงรายการเป็นพารามิเตอร์ทางเลือกพร้อมค่าเริ่มต้น ค่าเริ่มต้นสามารถใช้ได้เมื่อค่าเป็นตัวเลข แต่ต้องระบุขนาดหากค่าเป็นสตริง ดังนั้นในบางสถานการณ์ขนาดจึงเป็นทางเลือกในขณะที่บางสถานการณ์จำเป็นต้องใช้ และแบบสอบถามจะล้มเหลวหากไม่ได้ระบุไว้
สิ่งอื่นที่ฉันไม่ได้พิจารณา (หรือทดสอบ) คือฉันได้อ่านว่า ADODB สามารถใช้งานได้ทุกที่ที่มีไดรเวอร์ให้ ดังนั้นจึงสามารถใช้ในสมุดงาน Excel อาจเป็นไฟล์ข้อความและแหล่งข้อมูลอื่น ๆ แทนที่จะเป็นเพียงฐานข้อมูล ดังนั้นการสืบค้นแบบซิงโครนัสและอะซิงโครนัสอาจใช้งานได้เช่นกัน แต่นั่นไม่ใช่สิ่งที่ฉันกำหนดไว้เพื่อออกแบบหรือทดสอบ
ฉันขอขอบคุณคำวิจารณ์ที่สร้างสรรค์
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "cQueryable"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
'Requires a refernce to the Microsoft ActiveX Data Objects 6.1 Library (or equivalent)
Private WithEvents mASyncConn As ADODB.Connection
Attribute mASyncConn.VB_VarHelpID = -1
Private mSyncConn As ADODB.Connection
Private mConn As ADODB.Connection
Private mComm As ADODB.Command
Private mSql As String
Private mProcedureAfterQuery As String
Private mAsync As Boolean
Private mConnectionString As String
Private Const mSyncExecute As Long = -1
Private Sub Class_Initialize()
Set mComm = New ADODB.Command
Set mConn = New ADODB.Connection
End Sub
Public Property Let Sql(value As String)
mSql = value
End Property
Public Property Get Sql() As String
Sql = mSql
End Property
Public Property Let ConnectionString(value As String)
mConnectionString = value
End Property
Public Property Get ConnectionString() As String
ConnectionString = mConnectionString
End Property
Public Property Let procedureAfterQuery(value As String)
mProcedureAfterQuery = value
End Property
Public Property Get procedureAfterQuery() As String
procedureAfterQuery = mProcedureAfterQuery
End Property
Public Sub createParam(pName As String, pType As DataTypeEnum, pValue As Variant, Optional pDirection As ParameterDirectionEnum = adParamInput, Optional pSize As Long = 0)
Dim pm As ADODB.Parameter
With mComm
Set pm = .CreateParameter(name:=pName, Type:=pType, direction:=pDirection, value:=pValue, size:=pSize)
.Parameters.Append pm
End With
End Sub
Public Function SyncExecute()
Set mSyncConn = mConn
If connectionSuccessful Then
With mComm
.CommandText = mSql
Set .ActiveConnection = mSyncConn
Set SyncExecute = .execute(Options:=mSyncExecute)
End With
End If
End Function
Public Sub AsyncExecute()
Set mASyncConn = mConn
If connectionSuccessful Then
With mComm
.CommandText = mSql
Set .ActiveConnection = mASyncConn
.execute Options:=adAsyncExecute
End With
End If
End Sub
Private Function connectionSuccessful() As Boolean
If mConn.State = adStateClosed Then
mConn.ConnectionString = mConnectionString
End If
On Error GoTo errHandler
If mConn.State = adStateClosed Then
mConn.Open
End If
connectionSuccessful = (mConn.State = adStateOpen)
On Error GoTo 0
Exit Function
errHandler:
Debug.Print "Error: Connection unsuccessful"
connectionSuccessful = False
End Function
Private Sub mASyncConn_ExecuteComplete(ByVal RecordsAffected As Long, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pCommand As ADODB.Command, ByVal pRecordset As ADODB.Recordset, ByVal pConnection As ADODB.Connection)
If mProcedureAfterQuery <> "" Then
Call Application.Run(mProcedureAfterQuery, pRecordset)
End If
End Sub
คำตอบ
การเชื่อมต่อฟังก์ชันส่วนตัวประสบความสำเร็จ () เป็นบูลีน
ชื่อนี้บ่งบอกว่าคุณกำลังทดสอบเพื่อดูว่าการเชื่อมต่อถูกเปิดแล้วหรือไม่เมื่อในความเป็นจริงมันถูกใช้เพื่อเปิดการเชื่อมต่อและทดสอบว่าสำเร็จ
Private Function OpenConnection() As Boolean
ชื่อนี้บอกคุณว่าคุณกำลังเปิดการเชื่อมต่อ เนื่องจากประเภทการส่งคืนเป็นแบบบูลีนจึงเป็นเรื่องปกติที่จะถือว่าฟังก์ชันจะคืนค่าเป็น True ก็ต่อเมื่อการเชื่อมต่อสำเร็จ
การมีตัวจัดการข้อผิดพลาดหลีกเลี่ยงข้อผิดพลาดและพิมพ์ข้อความไปยังหน้าต่างทันทีนั้นเป็นผลดี ในฐานะนักพัฒนาฉันไม่ได้มองไปที่หน้าต่างทันทีโดยสัญชาตญาณสำหรับข้อความแสดงข้อผิดพลาด ในฐานะผู้ใช้ฉันจะแจ้งให้ผู้พัฒนาทราบถึงข้อความแสดงข้อผิดพลาดที่เกิดขึ้นและไม่อยู่ในจุดที่ส่งผลกระทบ เมื่อพิจารณาว่ารหัสของคุณใช้ขั้นตอนการติดต่อกลับไม่มีการรับประกันว่าจะมีข้อผิดพลาดเกิดขึ้น สิ่งเดียวที่มั่นใจได้ก็คือจะมีปัญหาบางอย่างที่เกิดขึ้น
แน่นอนคุณควรเพิ่มข้อผิดพลาดที่กำหนดเองเนื่องจากmConnectionString
ไม่ได้ตั้งค่า ไม่จำเป็นต้องมีข้อความแสดงข้อผิดพลาดที่กำหนดเองสำหรับการเชื่อมต่อที่ล้มเหลว (หากคุณลบตัวจัดการข้อผิดพลาด) เนื่องจากข้อผิดพลาด ADODB จะถูกส่งไปที่จุดที่เรียกขั้นตอนนี้
สาธารณะย่อย AsyncExecute ()
พิจารณาเพิ่มข้อผิดพลาดหากไม่ได้ตั้งค่าขั้นตอนการโทรกลับ
Private Sub Class_Terminate ()
ควรใช้วิธีนี้เพื่อปิดการเชื่อมต่อ
mConn, mASyncConn และ mSyncConn
ไม่จำเป็นต้องใช้ตัวแปรการเชื่อมต่อที่แตกต่างกันสามตัวแปร คุณกำลังทำงานมากขึ้นและทำให้โค้ดสับสน การใช้ตัวแปรเช่นAsyncMode As Boolean
จะให้ข้อเสนอแนะเดียวกันและลดความซับซ้อนของโค้ดทำให้อ่านง่ายขึ้น
หลักการตั้งชื่อ
การมีvalue
และexecute
ตัวพิมพ์เล็กจะเปลี่ยนกรณีสำหรับตัวแปรและคุณสมบัติอื่น ๆ ทั้งหมดที่มีชื่อเดียวกัน ด้วยเหตุนี้ฉันจึงใช้ Pascal Case สำหรับตัวแปรทั้งหมดที่ไม่มีคำนำหน้าบางประเภท
โรงงานของ Mathieu Guindon : การเริ่มต้นวัตถุพารามิเตอร์
การปรับปรุงอื่น ๆ ที่เป็นไปได้
กิจกรรมสาธารณะจะอนุญาตให้คุณใช้cQueryable
ในคลาสที่กำหนดเองอื่น ๆ
Public Event AsyncExecuteComplete(pRecordset As Recordset)
ความสามารถในการเชื่อมโยงข้อความค้นหาเข้าด้วยกันดูเหมือนจะเป็นแบบธรรมชาติ
Public Function NextQuery(Queryable AS cQueryable) AS cQueryable Set NextQuery = Queryable Set mQueryable = Queryable End Function
วิธีนี้จะช่วยให้คุณสามารถเรียกใช้การสืบค้นหลายรายการตามลำดับโดยไม่จำเป็นต้องเรียกกลับหลายครั้ง
CreateTempQuery.NextQuery(FillTempTableQuery).NextQuery(UpdateEmployeesTableQuery)