使用大量参数调用存储过程

时间:2015-01-23 16:47:12

标签: vba vb6 adodb

嘿我用这段代码得到这个错误,我不知道为什么。这将是一个很大的帮助,因为我试图让我的代码稍微更容易阅读

Public Function SaveProperty() As Boolean
'** Save Current Personal Data Record

' Error Checking
On Error GoTo Err_SaveProperty

' Dimension Local Variables
Dim uRecSnap As ADODB.Recordset
Dim uPar As ADODB.Parameter

' Check For Open Connection
If uDBase Is Nothing Then
    OpenConnection()
    bConnection = True
End If

' Run Stored Procedure - Save Property Record
uCommand = New ADODB.Command
With uCommand
    .ActiveConnection = uDBase
    .CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
    .CommandTimeout = 0
    .Parameters.Append.CreateParameter("@PropertyID", ADODB.DataTypeEnum.adInteger, ADODB.ParameterDirectionEnum.adParamInput, 50, Val(lblPropertyIDValue.Text))
    .Parameters.Append.CreateParameter("@PropertyManager", ADODB.DataTypeEnum.adLongVarChar, ADODB.ParameterDirectionEnum.adParamInput, 60, cmbPropertyManager.Text)
    .Parameters.Append.CreateParameter("@AddressLine1", ADODB.DataTypeEnum.adLongVarChar, ADODB.ParameterDirectionEnum.adParamInput, 30, txtAddress1.Text)
    .Parameters.Append.CreateParameter("@AddressLine2", ADODB.DataTypeEnum.adLongVarChar, ADODB.ParameterDirectionEnum.adParamInput, 30, txtAddress2.Text
'...ETC

.CommandText = "PropertyMaster_SaveRecord"

    .Execute()
End With

' Close Connection
uRecSnap = Nothing
uCommand = Nothing
If bConnection Then CloseConnection()
SaveProperty = True

Err_SaveProperty:
If Err.Number <> 0 Then
    sErrDescription = Err.Description
    WriteAuditLogRecord("clsProperty", "SaveProperty", "Error", sErrDescription)
    SaveProperty = False
End If

结束功能

我已经从这样的代码中减少了代码行

 uPar = .CreateParameter("@LandlordID", ADODB.DataTypeEnum.adInteger, ADODB.ParameterDirectionEnum.adParamInput)
    .Parameters.Append(uPar)
    .Parameters("@LandlordID").Value = Val(lblLandlordID.Text)

2 个答案:

答案 0 :(得分:4)

欢迎来到精彩With陈述的警告!

正如@RubberDuck所暗示的那样,你的问题就在这里:

.Parameters.Append.CreateParameter(...)

应该是:

.Parameters.Append .CreateParameter(...)

如果没有With阻止,您就会拥有:

uCommand.Parameters.Append uCommand.CreateParameter(...)

AppendCreateParameter都是uCommand块正在使用的With对象的成员。

答案 1 :(得分:1)

如果您真的想让您的代码更易于阅读,请执行以下操作:

' Run Stored Procedure - Save Property Record
Set uCommand = New ADODB.Command  'Note use of Set keyword
With uCommand
    .ActiveConnection = uDBase
    .CommandType = adCmdStoredProc 'Don't need the entire object hierarchy here
    .CommandTimeout = 0
    .CommandText = "PropertyMaster_SaveRecord"
    .Parameters.Refresh
    .Parameters(1) = cmbPropertyManager.Text 'Collections are usually 1-based in VB6
    .Parameters(2) = txtAddress1.Text
    .Parameters(3) = txtAddress2.Text
    '...ETC
    .Execute()
End With

这确实需要额外的往返来查找参数。但是,如果您能承受性能开销,那么这是更容易的方法。此外,它减少了潜在的维护开销,因为它没有紧密耦合到存储过程的参数列表;例如,您可以重命名存储过程中的参数,而不必担心破坏您的代码。

另请注意,在使用枚举时,您不需要拼写整个对象层次结构;事实上,我以前从没见过它。因此,不这样做也会使您的代码更容易阅读。

接下来,在实例化新对象时使用Set关键字。

最后,替换它:

If uDBase Is Nothing Then
    OpenConnection()
    bConnection = True
End If

有了这个:

If uDBase.State = adStateClosed Then
    OpenConnection()
    bConnection = True '?? Probably don't need this, see below
End If

您不想依赖于检查对象是否为空的原因是您可以关闭代码中其他位置的连接并忘记将uDBase设置为空。这可能会造成一个非常难以找到的错误。此外,如果您拥有bConnection变量的唯一原因是因为您使用它来跟踪您的连接是否打开,您可以安全地摆脱它并只使用State属性。

进一步的改进是将OpenConnection例程更改为GetConnection例程,并封装所有对打开连接的检查等等。像这样:

Public Function GetConnection() As ADODB.Connection
    Static myConn As ADODB.Connection
    If myConn.State = adStateClosed Then
        Set myConn = New ADODB.Connection
        myConn.Open "myConnectionString"
    End If
    GetConnection = myConn
End Function

这假设您在整个应用程序中使用一个连接,并且在应用程序运行时保持打开状态。这是uDBase变量的范围所暗示的。当然,还有更经济的方式来管理连接,根据您处理的流量,您可能需要查看这些方法。