使用输出参数从 C# 调用外部 AS400 存储过程

Calling an external AS400 stored procedure from C# with output parameter

我的存储过程有 4 个参数:3 个字符串作为输入,1 个字符串作为输出。

using (OdbcConnection cn = ODBC.Instance.AmulibConnection)
{
    cn.Open();

    using (OdbcCommand cm = cn.CreateCommand())
    {
        cm.CommandText = "CALL RET_IMPL_STS('?','?','?','?')";
        cm.CommandType = CommandType.StoredProcedure;

        cm.Parameters.Add("@P1", OdbcType.Char).Value = "1";
        cm.Parameters["@P1"].Size = 1;
        cm.Parameters["@P1"].Direction = ParameterDirection.Input;

        cm.Parameters.Add("@P2", OdbcType.Char).Value = "ABC";
        cm.Parameters["@P2"].Size = 15;
        cm.Parameters["@P2"].Direction = ParameterDirection.Input;

        cm.Parameters.Add("@P3", OdbcType.Char).Value = "DEF";
        cm.Parameters["@P3"].Size = 6;
        cm.Parameters["@P3"].Direction = ParameterDirection.Input;

        cm.Parameters.Add("@P4", OdbcType.Char);
        cm.Parameters["@P4"].Size = 5;
        cm.Parameters["@P4"].Direction = ParameterDirection.Output;

        cm.Prepare();
        cm.ExecuteNonQuery();

        string result = cm.Parameters["@P4"].Value.ToString();

        return result;
    }
}

我收到以下错误:

Additional information: ERROR [HY000] [IBM][System i Access ODBC Driver][DB2 for i5/OS]SQL0469 - IN, OUT, or INOUT not valid for parameter 4 in procedure RET_IMPL_STS in *N.

输出参数的正确语法是什么?

乍一看,您似乎少了一些花括号。尝试使用以下命令创建一个新的 OdbcCommand 对象

OdbcCommand cm = new OdbcCommand("{CALL RET_IMPL_STS('?','?','?','?')}", cn);

请阅读更多内容:https://support.microsoft.com/en-us/kb/310130

阅读@Andrei 的 link 我找到了这一段:

When a stored procedure returns a resultset, the output parameter(s) and return value are not available until the resultset has been accessed and closed. For example, if we omitted the line "dr.Close()" in the second sample above, we would be unable to retrieve the values for the output parameter and the return value.

以下是 2 个可能的选项:

  1. 即使参数是字符串我们也需要去掉引号:

    cm.CommandText = "CALL RET_IMPL_STS(?,?,?,?)";

    然后我们需要指定每个4个参数

  2. 以下语法也可以正常工作:

    cm.CommandText = string.Format("CALL RET_IMPL_STS ('{0}', '{1}', '{2}', ?)", STIDAD, ITNOAD, ITRVAD);

    在那种情况下,我们只需要指定输出参数。请注意,在这种格式中,字符串参数需要引号。

我建议您使用 IBM cwbx 库。这是为桌面和 IBM AS400 之间的互操作编程而创建的 IBM 库。

看这里:http://timtrott.co.uk/calling-ibm-iseries-rpg-programs-api-calls/ 这告诉您如何使用位于 IBM AS400 上的参数和 return 一些值来调用过程。相信我,我已经完成了这个任务并且它成功了。

整个事情只是包括 cwbx.dll 文件,创建机器和程序对象的实例,用 ProgrammParameters 填充它们(定义输入、输出和 inout 参数)并调用它.

using System;
using System.Collections.Generic;
using System.Text;
using cwbx;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string result = string.Empty;

            StringConverter stringConverter = new StringConverterClass();

            // Define an AS400 system and connect to it
            AS400System system = new AS400System();
            system.Define("AS400");
            system.UserID = "USERNAME";
            system.Password = "PASSWORD";
            system.IPAddress = "127.0.0.1";
            system.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd);

            // Check the connection
            if (system.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) == 1)
            {
                // Create a program object and link to a system                
                cwbx.Program program = new cwbx.Program();
                program.LibraryName = "LIBRARY";
                program.ProgramName = "RPGPROG";
                program.system = system;

                // Sample parameter data
                char chrValue = '1';
                string strValue1 = "ABC";
                string strValue2 = "DEF";
                string outp = "";

                // Create a collection of parameters associated with the program
                ProgramParameters parameters = new ProgramParameters();

                parameters.Append("P1", cwbrcParameterTypeEnum.cwbrcInput, 1);
                parameters["P1"].Value = chrValue;

                parameters.Append("P2"), cwbrcParameterTypeEnum.cwbrcInput, 3);
                parameters["P2"].Value = strValue1;

                parameters.Append("P3"), cwbrcParameterTypeEnum.cwbrcInput, 3);
                parameters["P3"].Value = strValue1;

                parameters.Append("P4", cwbrcParameterTypeEnum.cwbrcOutput, 3);


                outp = stringConverter.FromBytes(parameters["P4"].Value);
            }

            system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll);
            Console.WriteLine(result);
            Console.ReadKey();
        }
    }
}

这应该几乎可以工作,你必须小心,因为接口 dll 对错误的参数长度很敏感。所以如果要传输"TEXT",提供textlength为3,那么只传输"TEX"。

您应该像 here

一样为 .net 使用 dll ibm 数据提供程序

不过你可以尝试修改你的代码

OdbcCommand cm = new OdbcCommand("{CALL RET_IMPL_STS('?','?','?','?')}", cn);
....
cm.Parameters["@P4"].Direction = ParameterDirection.InputOutput;