Advanced Features
This document introduces the advanced features and best practices of the cDataBase class library, helping you make better use of the database class.
Table of Contents
- Asynchronous Execution
- Connection Pool Management
- Batch Operation Optimization
- Performance Optimization Tips
- Error Handling Strategy
- Design Pattern Applications
- Common Problem Solutions
Asynchronous Execution
Async Property
The Async property enables asynchronous SQL execution without blocking the main thread.
Syntax
vb
Property Get Async() As cDataBaseExample
vb
' Asynchronous INSERT execution
db.Sql("INSERT INTO logs (message) VALUES ('test')").Async.Exec
' Listen for completion event
Private Sub db_AsyncExecuteComplete(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 pError Is Nothing Then
Debug.Print "Async execution successful, rows affected: " & RecordsAffected
Else
Debug.Print "Async execution failed: " & pError.Description
End If
End SubAsynchronous Execution Scenarios
vb
' Scenario 1: Logging (non-blocking main flow)
Sub LogMessage(sMessage As String)
db.Sql("INSERT INTO logs (message, created_at) VALUES (?, ?)") _
.Param("message", sMessage, VBMAN.adVarWChar) _
.Param("created_at", Now, VBMAN.adDate) _
.Async.ExecParam
' Don't wait for execution to complete, continue with subsequent code
End Sub
' Scenario 2: Batch data processing
Sub ProcessLargeDataset()
' Main thread continues processing
ProcessData
' Save results asynchronously
db.Sql("INSERT INTO results SELECT * FROM temp_table").Async.Exec
End SubConnection Pool Management
Multiple Database Connections
Use connection pool to manage multiple database connections.
vb
Dim db As New VBMAN.cDataBase
' Main database
db.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "maindb"
' Log database
Dim dbLog As VBMAN.cDataBase
Set dbLog = db.ConnInst("log", False)
dbLog.Connect VBMAN.enumDbType_Mysql, "192.168.1.100:3306", "loguser", "pwd", "logdb"
' Cache database
Dim dbCache As VBMAN.cDataBase
Set dbCache = db.ConnInst("cache", False)
dbCache.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "cachedb"
' Use different databases
db.Sql("SELECT * FROM users").Query
dbLog.Sql("INSERT INTO logs (msg) VALUES ('test')").Exec
dbCache.Sql("SELECT * FROM cache_data").QueryDynamic Connection Management
vb
' Create connections dynamically based on configuration
Function GetDatabase(sConfigName As String) As VBMAN.cDataBase
Dim dbInst As VBMAN.cDataBase
Set dbInst = db.ConnInst(sConfigName, False)
' Connect to different databases based on configuration
Select Case sConfigName
Case "main"
dbInst.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "maindb"
Case "backup"
dbInst.Connect VBMAN.enumDbType_Mysql, "192.168.1.100:3306", "user", "pwd", "backupdb"
Case "readonly"
dbInst.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "readonly", "pwd", "maindb"
End Select
Set GetDatabase = dbInst
End Function
' Usage
Dim dbMain As VBMAN.cDataBase
Set dbMain = GetDatabase("main")
dbMain.Sql("SELECT * FROM users").QueryConnection Cleanup
vb
' Remove specified connection
db.ConnInstRemove "log"
' Remove all connections
db.ConnInstRemove ""Batch Operation Optimization
Batch Insert Optimization
vb
' Method 1: Using BatchInsert (recommended)
Sub BatchInsertUsers(colUsers As Collection)
If db.BatchInsert("users", colUsers) Then
Debug.Print "Batch insert successful"
End If
End Sub
' Method 2: Using transaction + loop
Sub BatchInsertUsers2(colUsers As Collection)
db.TransBegin
Dim i As Long
For i = 1 To colUsers.Count
Dim dictUser As Scripting.Dictionary
Set dictUser = colUsers(i)
Dim sSql As String
sSql = "INSERT INTO users (name, age) VALUES ('" & _
db.Escape(dictUser("name")) & "', " & dictUser("age") & ")"
If Not db.Sql(sSql).Exec Then
db.TransRollback
Exit Sub
End If
Next
db.TransCommit
End Sub
' Method 3: Using VALUES clause (SQL Server/MySQL)
Sub BatchInsertUsers3(colUsers As Collection)
Dim sSql As String
sSql = "INSERT INTO users (name, age) VALUES "
Dim i As Long
For i = 1 To colUsers.Count
Dim dictUser As Scripting.Dictionary
Set dictUser = colUsers(i)
If i > 1 Then sSql = sSql & ", "
sSql = sSql & "('" & db.Escape(dictUser("name")) & "', " & dictUser("age") & ")"
Next
db.Sql(sSql).Exec
End SubBatch Update Optimization
vb
' Use transaction for batch update
Sub BatchUpdateUsers(colUpdates As Collection)
db.TransBegin
Dim i As Long
For i = 1 To colUpdates.Count
Dim dictUpdate As Scripting.Dictionary
Set dictUpdate = colUpdates(i)
If Not db.Sql("UPDATE users SET name = ?, age = ? WHERE id = ?") _
.Param("name", dictUpdate("name"), VBMAN.adVarWChar) _
.Param("age", dictUpdate("age"), VBMAN.adInteger) _
.Param("id", dictUpdate("id"), VBMAN.adInteger) _
.ExecParam Then
db.TransRollback
Exit Sub
End If
Next
db.TransCommit
End SubPerformance Optimization Tips
1. Use Indexed Fields
vb
' Recommended: Use indexed fields as conditions
db.Sql("SELECT * FROM users WHERE id = 1").Query
' Not recommended: Use non-indexed fields
db.Sql("SELECT * FROM users WHERE name = 'John'").Query2. Only Query Needed Fields
vb
' Recommended: Only query needed fields
db.Sql("SELECT id, name FROM users").Query
' Not recommended: Query all fields
db.Sql("SELECT * FROM users").Query3. Use Appropriate Cursor Types
vb
' Recommended: Use ForwardOnly for read-only queries
db.Sql("SELECT * FROM users").Query adOpenForwardOnly, adLockReadOnly
' Not recommended: Use default cursor (may be slower)
db.Sql("SELECT * FROM users").Query4. Limit Result Set Size
vb
' Recommended: Use TOP/LIMIT to limit results
db.Sql("SELECT TOP 100 * FROM users").Query
' Not recommended: Query all data
db.Sql("SELECT * FROM users").Query5. Use Pagination
vb
' Recommended: Use pagination
db.Sql("SELECT * FROM users").Page(1, 20).Query
' Not recommended: Query all data at once
db.Sql("SELECT * FROM users").Query6. Cache Query Results
vb
' Cache query results
Private m_colCachedUsers As Collection
Private m_dtCacheTime As Date
Function GetUsers() As Collection
' Cache for 5 minutes
If DateDiff("s", m_dtCacheTime, Now) > 300 Or m_colCachedUsers Is Nothing Then
If db.Sql("SELECT * FROM users").Fetch Then
Set m_colCachedUsers = db.Rows
m_dtCacheTime = Now
End If
End If
Set GetUsers = m_colCachedUsers
End FunctionError Handling Strategy
Unified Error Handling
vb
' Unified error handling function
Function ExecuteSQL(sSql As String) As Boolean
On Error GoTo ErrHandler
If db.Sql(sSql).Exec Then
ExecuteSQL = True
Else
LogError "SQL execution failed", db.LastErr
ExecuteSQL = False
End If
Exit Function
ErrHandler:
LogError "Exception occurred", Err.Description
ExecuteSQL = False
End Function
' Error logging
Sub LogError(sOperation As String, sError As String)
' Log to file or database
Debug.Print Now & " - " & sOperation & ": " & sError
End SubRetry Mechanism
vb
' Query with retry
Function QueryWithRetry(sSql As String, Optional lMaxRetries As Long = 3) As Boolean
Dim lRetry As Long
For lRetry = 1 To lMaxRetries
If db.Sql(sSql).Query Then
QueryWithRetry = True
Exit Function
End If
' Check connection
If Not db.CheckConnection Then
db.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "mydb"
End If
' Wait and retry
Sleep 1000
Next
QueryWithRetry = False
End FunctionDesign Pattern Applications
Singleton Pattern
vb
' Database singleton
Private m_DB As VBMAN.cDataBase
Function GetDatabase() As VBMAN.cDataBase
If m_DB Is Nothing Then
Set m_DB = New VBMAN.cDataBase
m_DB.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "mydb"
End If
Set GetDatabase = m_DB
End FunctionFactory Pattern
vb
' Database factory
Function CreateDatabase(sType As String) As VBMAN.cDataBase
Dim db As New VBMAN.cDataBase
Select Case sType
Case "main"
db.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "maindb"
Case "log"
db.Connect VBMAN.enumDbType_Mysql, "192.168.1.100:3306", "loguser", "pwd", "logdb"
Case "cache"
db.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "cachedb"
End Select
Set CreateDatabase = db
End FunctionRepository Pattern
vb
' User repository
Class cUserRepository
Private m_DB As VBMAN.cDataBase
Private Sub Class_Initialize()
Set m_DB = New VBMAN.cDataBase
m_DB.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "mydb"
End Sub
Function GetById(lId As Long) As Scripting.Dictionary
If m_DB.Sql("SELECT * FROM users WHERE id = ?") _
.Param("id", lId, VBMAN.adInteger) _
.QueryParam Then
If m_DB.Rows.Count > 0 Then
Set GetById = m_DB.Row
End If
End If
End Function
Function GetAll() As Collection
If m_DB.Sql("SELECT * FROM users").Fetch Then
Set GetAll = m_DB.Rows
End If
End Function
Function Save(dictUser As Scripting.Dictionary) As Boolean
If m_DB.Sql("INSERT INTO users (name, age) VALUES (?, ?)") _
.Param("name", dictUser("name"), VBMAN.adVarWChar) _
.Param("age", dictUser("age"), VBMAN.adInteger) _
.ExecParam Then
Save = True
Else
Save = False
End If
End Function
End ClassCommon Problem Solutions
Q1: Connection Timeout
Problem: Connection to database times out.
Solution:
vb
' Set connection timeout
db.Conn.ConnectionTimeout = 30 ' 30 seconds
db.Connect VBMAN.enumDbType_MsSql, "127.0.0.1,1433", "sa", "pwd", "mydb"Q2: Query Timeout
Problem: Query execution takes too long.
Solution:
vb
' Set command timeout
db.Conn.CommandTimeout = 60 ' 60 seconds
db.Sql("SELECT * FROM large_table").QueryQ3: Out of Memory
Problem: Querying large amounts of data causes memory exhaustion.
Solution:
vb
' Use pagination query
db.Sql("SELECT * FROM large_table").Page(1, 1000).Query
' Or use streaming
If db.Sql("SELECT * FROM large_table").Query Then
Do Until db.Rs.EOF
' Process single record
ProcessRecord db.Rs
db.Rs.MoveNext
Loop
End IfQ4: Concurrency Conflicts
Problem: Multiple operations execute simultaneously causing conflicts.
Solution:
vb
' Use transaction and locking
db.TransBegin
db.Sql("SELECT * FROM users WHERE id = 1").Query adOpenKeyset, adLockPessimistic
' Process data
db.Sql("UPDATE users SET ...").Exec
db.TransCommitBest Practices Summary
1. Connection Management
- Connect when needed, disconnect when done
- For frequent operations, keep the connection alive
- Use connection pool to manage multiple connections
2. Query Optimization
- Use indexed fields as conditions
- Only query needed fields
- Use pagination to limit result sets
- Use appropriate cursor types
3. Security Protection
- Always use parameterized queries
- Validate user input
- Use transactions to ensure consistency
4. Error Handling
- Always check return values
- Log errors
- Implement retry mechanism
5. Code Organization
- Use design patterns
- Encapsulate common operations
- Keep code clean
Last Updated: 2026-01-21