Skip to main content
adds extra note on assignments
Source Link
ThunderFrame
  • 2k
  • 2
  • 16
  • 28

Assigning ActiveConnection

`ActiveConnection` is an object whose default property is `ConnectionString`. When assigning the `ActiveConnection` property, it is better practice to always use `Set`, although ADODB will manage things behind the scenes if you forget and just assign the `ConnectionString` property.
Public Function ExecuteNonQuery(connection As ADODB.connection, sql As String, ParamArray parameterValues()) As Long

    Dim cmd As New ADODB.Command
    Set cmd.ActiveConnection = connection
    cmd.CommandType = adCmdText
    cmd.CommandText = sql

    Dim i As Integer
    Dim value As Variant
    For i = LBound(parameterValues) To UBound(parameterValues)
        value = parameterValues(i)
        cmd.parameters.Append ToSqlInputParameter(value)
    Next

    Dim result As Long
    On Error Resume Next
        Dim recordsAffected As Long
        cmd.Execute recordsAffected, Options:=ExecuteOptionEnum.adExecuteNoRecords
        If Err.Number = 0 Then
          result = recordsAffected
        Else
          result = -1
        End If
    On Error GoTo 0
    ExecuteNonQuery = result
End Function
Public Function ExecuteNonQuery(connection As ADODB.connection, sql As String, ParamArray parameterValues()) As Long

    Dim cmd As New ADODB.Command
    cmd.ActiveConnection = connection
    cmd.CommandType = adCmdText
    cmd.CommandText = sql

    Dim i As Integer
    Dim value As Variant
    For i = LBound(parameterValues) To UBound(parameterValues)
        value = parameterValues(i)
        cmd.parameters.Append ToSqlInputParameter(value)
    Next

    Dim result As Long
    On Error Resume Next
        Dim recordsAffected As Long
        cmd.Execute recordsAffected, Options:=ExecuteOptionEnum.adExecuteNoRecords
        If Err.Number = 0 Then
          result = recordsAffected
        Else
          result = -1
        End If
    On Error GoTo 0
    ExecuteNonQuery = result
End Function

Assigning ActiveConnection

`ActiveConnection` is an object whose default property is `ConnectionString`. When assigning the `ActiveConnection` property, it is better practice to always use `Set`, although ADODB will manage things behind the scenes if you forget and just assign the `ConnectionString` property.
Public Function ExecuteNonQuery(connection As ADODB.connection, sql As String, ParamArray parameterValues()) As Long

    Dim cmd As New ADODB.Command
    Set cmd.ActiveConnection = connection
    cmd.CommandType = adCmdText
    cmd.CommandText = sql

    Dim i As Integer
    Dim value As Variant
    For i = LBound(parameterValues) To UBound(parameterValues)
        value = parameterValues(i)
        cmd.parameters.Append ToSqlInputParameter(value)
    Next

    Dim result As Long
    On Error Resume Next
        Dim recordsAffected As Long
        cmd.Execute recordsAffected, Options:=ExecuteOptionEnum.adExecuteNoRecords
        If Err.Number = 0 Then
          result = recordsAffected
        Else
          result = -1
        End If
    On Error GoTo 0
    ExecuteNonQuery = result
End Function
Source Link
ThunderFrame
  • 2k
  • 2
  • 16
  • 28

Waking this one up...

ExecuteNonQuery

Return value never assigned

`ExecuteNonQuery` never has its return value assigned.

Return value type

You have an opportunity here to return a richer value than a Boolean. Very often when executing a command, you're interested in the number of records affected. You can return the number of records affected, or -1 if there is an error.

Execution Options

You're not explicitly setting any Options on the ADODB.Command.Execute. As per MSDN:

Use the ExecuteOptionEnum value adExecuteNoRecords to improve performance by minimizing internal processing.

Public Function ExecuteNonQuery(connection As ADODB.connection, sql As String, ParamArray parameterValues()) As Long

    Dim cmd As New ADODB.Command
    cmd.ActiveConnection = connection
    cmd.CommandType = adCmdText
    cmd.CommandText = sql

    Dim i As Integer
    Dim value As Variant
    For i = LBound(parameterValues) To UBound(parameterValues)
        value = parameterValues(i)
        cmd.parameters.Append ToSqlInputParameter(value)
    Next

    Dim result As Long
    On Error Resume Next
        Dim recordsAffected As Long
        cmd.Execute recordsAffected, Options:=ExecuteOptionEnum.adExecuteNoRecords
        If Err.Number = 0 Then
          result = recordsAffected
        Else
          result = -1
        End If
    On Error GoTo 0
    ExecuteNonQuery = result
End Function

CreateCommand factory method

Checking for valid ParamArray arguments

As per MSDN

If IsMissing is used on a ParamArray argument, it always returns False. To detect an empty ParamArray, test to see if the array's upper bound is less than its lower bound.

Despite the documentation above, IsMissing does actually seem to return True when the ParamArray argument is missing, but it's still safer to check the array bounds.

You obviously have a private helper function in IsArrayInitialized, but it is not necessary - if the ParamArray variable is "missing", it will be an array, but its upperbound will be -1, and its lowerbound will be 0, so the For statement is sufficient.

Private Function CreateCommand(connection As ADODB.connection, ByVal cmdType As ADODB.CommandTypeEnum, ByVal sql As String, parameterValues() As Variant) As ADODB.Command

    Dim cmd As New ADODB.Command
    cmd.ActiveConnection = connection
    cmd.CommandType = cmdType
    cmd.CommandText = sql

    Dim i As Integer
    Dim value As Variant

    For i = LBound(parameterValues) To UBound(parameterValues)
        value = parameterValues(i)
        cmd.parameters.Append ToSqlInputParameter(value)
    Next

    Set CreateCommand = cmd

End Function

Having said that, you're going through some variable gymnastics to pass a ParamArray argument to a private method. You can avoid that by declaring the helper function's parameterValues parameter as ByVal parameterValues As Variant, but then you do need to check that it is an array before enumerating it.

Private Function CreateCommand(connection As ADODB.connection, ByVal cmdType As ADODB.CommandTypeEnum, ByVal sql As String, ByVal parameterValues As Variant) As ADODB.Command

    Dim cmd As New ADODB.Command
    cmd.ActiveConnection = connection
    cmd.CommandType = cmdType
    cmd.CommandText = sql

    Dim i As Integer
    Dim value As Variant

    If IsArray(parameterValues) Then

        For i = LBound(parameterValues) To UBound(parameterValues)
            value = parameterValues(i)
            cmd.parameters.Append ToSqlInputParameter(value)
        Next

    End If

    Set CreateCommand = cmd

End Function

Then, you can simplify a public method like ExecuteStoredProc to:

Public Function ExecuteStoredProc(connection As ADODB.connection, ByVal spName As String, ParamArray parameterValues()) As ADODB.Recordset

    Set ExecuteStoredProc = CreateCommand(connection, adCmdStoredProc, spName, values).Execute

End Function