ADO.Net 使用 iSeries 连接执行 DB2 存储过程返回池化输出参数值的连接

ADO.Net connection executing DB2 stored procedure returning pooled output parameter values using iSeries connection

[编辑 - 此问题已解决。问题与存储过程中未初始化的输出参数有关。]

为什么我需要关闭连接池才能使其正常工作??? [编辑 - 连接池释放了 AS400 上的共享连接内存区域]

在我的 MVC Web 应用程序中,我调用了 DB2 存储过程 (SP)。 这个SP有多个输入输出参数类似于这个伪代码:

CreatePO(@REQNO[in], @PO[out], @Approver[out], @ErrorMsg[out])

我的应用程序在处理过程中将数据写入此 SP 使用的表,因此当所有数据就位时,我调用 SP 并尝试创建 PO。

如果 PO 创建失败,@ErrorMsg out 参数中将出现错误消息。在这些情况下,@PO 和@Approver 参数应为空白。

顺序如下:

1) 我尝试创建我的第一个采购订单,但出现问题...
CreatePO(100, 空白, 空白, 空白)
这导致...
CreatePO(100, blank, blank, 'unable to determine approver')

2) 我成功创建了第二个采购订单...
CreatePO(101, 空白, 空白, 空白)
CreatePO(101, 'P1234', 'JJONES', 空白)

3) 我尝试为@REQNO 100
重新创建采购订单 CreatePO(100, 空白, 空白, 空白)
CreatePO(100, 'P1234', 'JJONES', 'unable to determine approver')

第 3 步有冲突的参数。应用程序池正在返回步骤 2 中的 PO 和批准者以及相应的错误消息。

如果我回收我的 IIS 应用程序池,那么结果会回到步骤 #1 中发生的情况。

我将 "pooling=false" 添加到连接字符串,可以获得预期的结果。但是为什么连接池会以这种方式影响输出参数?这看起来更像是一个错误,而不是某种理想的缓存方法。

如果我不粘贴我的代码,有人会变形,所以这里是...

(看上面两行的末尾)

    'Dim cs As String = "DataSource=mydb;UserID=myuser;Password=mypassword;Naming=System;ConnectionTimeout=180; DefaultIsolationLevel=ReadUncommitted;AllowUnsupportedChar=True;CharBitDataAsString=True; TransactionCompletionTimeout=0;pooling=false"
    Dim cs As String = "DataSource=mydb;UserID=myuser;Password=mypassword;Naming=System;ConnectionTimeout=180; DefaultIsolationLevel=ReadUncommitted;AllowUnsupportedChar=True;CharBitDataAsString=True; TransactionCompletionTimeout=0;"
    Using conn As New iDB2Connection(cs) 
        conn.Open()
        Dim cmd As iDB2Command = New iDB2Command()
        cmd.Connection = conn 

        cmd.CommandType = CommandType.StoredProcedure
        cmd.CommandText = "BF6360CL"

        ' Input parameters
        cmd.Parameters.Add(New iDB2Parameter With {.ParameterName = "@REQNO", .DbType = SqlDbType.Char, .Size = 7, .Value = model.RO})

        ' Output parameters
        Dim opo = New iDB2Parameter With {.ParameterName = "@POORDER", .DbType = SqlDbType.Char, .Size = 7, .Direction = ParameterDirection.Output}
        cmd.Parameters.Add(opo)

        Dim oApprover = New iDB2Parameter With {.ParameterName = "@APPROVER", .DbType = SqlDbType.Char, .Size = 10, .Direction = ParameterDirection.Output}
        cmd.Parameters.Add(oApprover)

        Dim oStatus = New iDB2Parameter With {.ParameterName = "@STATUS", .DbType = SqlDbType.Char, .Size = 3, .Direction = ParameterDirection.Output}
        cmd.Parameters.Add(oStatus)

        Dim oErr = New iDB2Parameter With {.ParameterName = "@ERROR", .DbType = SqlDbType.Char, .Size = 1, .Direction = ParameterDirection.Output}
        cmd.Parameters.Add(oErr)

        ' return value
        Dim oRetval = New iDB2Parameter With {.ParameterName = "@RETURN_VALUE", .DbType = SqlDbType.Char, .Size = 10, .Direction = ParameterDirection.ReturnValue}
        cmd.Parameters.Add(oRetval)

        cmd.ExecuteNonQuery()

        model.PO = opo.Value
        model.Approver = oApprover.Value
        model.Status = oStatus.Value
        model.Err = oErr.Value

    End Using
return model

所以最大的问题是: 到底为什么连接池要负责输出参数值??? 这可能是 IBM iSeries iDB2Connection 实现中的错误吗?

IIS 应用程序池按名称缓存存储过程输出参数,并在检测到空值时返回缓存值。这发生在 ODBC 或 iSeries 连接上。当我回收应用程序池时,这个缓存值消失了。我在连接字符串中添加了“pooling=false;”这些缓存值将不再出现。

我的老板让我尝试使用 iSeries Navigator 调用存储过程,只是为了查看输出参数包含的内容。男孩让我感到惊讶。

原来是存储过程(SP)出了问题。今天早上我和 AS400 RPG 开发人员坐在一起,看着他们调试 SP。问题与未初始化的内存有关。

这是 SP 的定义: BF6360CL(@REQNO, @USER, @ENVIRONMENT, @PO[out], @Approver[out], @Status[out], @Error[out])

然后我在 iSeries Navigator 中重置与 AS400 的连接,输出参数重置回
4 = S2.RETU
5 = RN_VAR0000
等...

AS400 开发人员正在更改以初始化变量。当他们完成后,我希望能够将我的程序改回使用连接池。

当我重置 IIS 应用程序池时,它重置了我与数据库的连接。这似乎释放了 AS400 上分配的内存。

如果有人有更多关于连接和 AS400 输出参数内存的细节,请分享。