【问题标题】:Calling a Parameterized Stored Procedure in C# that returns values through a cursor and store it in a DataTable在 C# 中调用参数化存储过程,通过游标返回值并将其存储在 DataTable 中
【发布时间】:2018-05-03 08:04:43
【问题描述】:

我有一个存储过程,它通过游标运行选择查询并返回游标(原始选择查询更复杂,我已将其缩短)。

CREATE OR REPLACE PROCEDURE GETASSIGNEDROLES(IN V_USER_ID INTEGER) SPECIFIC GETASSIGNEDROLES DYNAMIC RESULT SETS 1 LANGUAGE SQL NOT DETERMINISTIC EXTERNAL ACTION READS SQL DATA CALLED ON NULL INPUT INHERIT SPECIAL REGISTERS 
BEGIN 
    DECLARE TEMP_CURSOR CURSOR WITH HOLD WITH RETURN TO CLIENT FOR 
        SELECT DISTINCT ROLE_ID, ROLE_NAME FROM ROLE ORDER BY ROLE_NAME FOR READ ONLY WITH UR; 
    IF V_USER_ID IS NOT NULL AND V_USER_ID > 0 THEN 
        OPEN TEMP_CURSOR; 
    END IF; 
END;

现在,我找不到任何示例来说明如何从返回游标的存储过程中获取值。我相信它与仅包含 select 语句的所有其他存储过程相同吗?

另外,我的数据库是 DB2,所以语法有点不同。到目前为止,在看了几个关于 SO 的问题后,我得到了以下代码。但是我使用Datatable并在CMD中传递参数并没有发现任何问题,这是正确的吗?

DataTable DT = new DataTable();
using (var connection = new DB2Connection(ConnectionString))
{
  //connection.Open(); //open/close connection will be done implicitely by the DataAdapter.
  using (DB2Command cmd = connection.CreateCommand())
  {
      cmd.CommandText = "GETASSIGNEDROLES";
      cmd.CommandType = CommandType.StoredProcedure;
      cmd.Parameters.Add(new DB2Parameter(DataBaseObjects.ParamVUserID, DB2Type.Integer)).Value = userDo.User_ID;
      //cmd.CommandTimeout = CommandTimeout; //wait time before terminating the attempt to execute a command and generating an error in secs

      using (var da = new DB2DataAdapter(cmd))
      {
          da.Fill(DT);
      }
      DT.TableName = TableName;
      return DT;
  }
}

【问题讨论】:

  • P.S.这是我第一次问问题,请放轻松。我是新来的。另外,为什么互联网上的 DB2 这么少。一切都是为了SQLServer,很少有与DB2相关的文章。文档没有关于它们的示例。

标签: c# stored-procedures datatable parameters db2


【解决方案1】:

有必要为您的 Db2 版本研究 Db2 知识中心的所有相关/链接页面,这些页面描述了 C# .net 公共语言运行时过程。

启动here 并研究每个链接的页面,使示例适用于您的环境。

如果您的 Db2 服务器在 Microsoft-Windows 上运行,或者如果您使用完整的数据服务器客户端安装了特定于 Windows 的 Db2 示例(默认位置是:

\程序文件\ibm\sqllib\samples\dotnet\cs

) 然后您可以在那里查看 C# 的 DataTable 示例,也可以在知识中心在线查看 - “DbDatMap.cs”和相关文件以及“SpClient.cs”及其依赖项

请检查您为什么填充DataTable DT 而填充return DTT

如果您调试代码,您应该能够在 da.Fill(DT); 之后迭代 DT 中的行。成功完成。

使用您的大部分语法的 consoleApp 对我来说都很好,唯一的变化是我使用了预先存在的连接,并为我的存储过程提供了一个 varchar 参数而不是整数(但这不会有所作为)。

【讨论】:

  • 存储过程已完成,并且已经与许多预先存在的程序/实用程序一起使用。另外,我想使用 DB2DataAdapter 而不是 DB2DataReader,因为我不希望结果按行返回。我希望它在数据表中。我已经有一个与此类似的工作代码,它只执行一个查询并将结果存储在一个数据表中,但我是第一次使用参数并返回一个值。
  • ">在调用 Fill 之前,您似乎缺少一个 da.SelectCommand。"当我使用以下代码时,我认为这是隐含的:使用 (var da = new DB2DataAdapter(cmd)) 而不是使用这个:DB2DataAdapter da = new DB2DataAdapter(); da.SelectCommand = cmd;
【解决方案2】:

所以我终于开始工作了。关于打开的游标,显然这就是您在 DB2 中的做法。光标保持打开状态以供客户端应用程序读取。此链接有帮助:https://bytes.com/topic/db2/answers/465403-how-do-well-anything-db2-sql

使用的存储过程(根据问题修改):

CREATE OR REPLACE PROCEDURE GETASSIGNEDROLES(IN V_USER_ID INTEGER, IN V_BUSINESS_ENTITY_ID INTEGER) SPECIFIC GETASSIGNEDROLES DYNAMIC RESULT SETS 1 LANGUAGE SQL NOT DETERMINISTIC EXTERNAL ACTION READS SQL DATA CALLED ON NULL INPUT INHERIT SPECIAL REGISTERS 
BEGIN 
    DECLARE TEMP_CURSOR CURSOR WITH HOLD WITH RETURN TO CLIENT FOR 
        SELECT DISTINCT ROLE_ID, ROLE_NAME FROM ROLE ORDER BY ROLE_NAME FOR READ ONLY WITH UR; 
    IF V_USER_ID IS NOT NULL AND V_USER_ID > 0 THEN 
        OPEN TEMP_CURSOR; 
    END IF; 
END;

C#中调用存储过程并将检索到的数据保存在数据表中的函数:

public DataTable GetAssignedRolesForUser(string ConnectionString, string TableName, User userDo)
        {
            //LogManager.EventLog("Inside GetAssignedRolesForUser");
            try
            {
                DataTable DTT = new DataTable();
                //See if UserID exists check is required here
                using (var connection = new DB2Connection(ConnectionString))
                {
                    //connection.Open(); //open/close connection will be done implicitely by the DataAdapter.
                    using (DB2Command cmd = connection.CreateCommand())
                    {
                        cmd.CommandText = DataBaseObjects.spGetAssignedRoles;
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.Add(new DB2Parameter(DataBaseObjects.ParamVUserID, DB2Type.Integer)).Value = userDo.User_ID;
                        cmd.Parameters.Add(new DB2Parameter(DataBaseObjects.ParamVBusinessEntityID, DB2Type.Integer)).Value = ConfigurationManager.AppSettings["BusinessEntity"];
                        //cmd.CommandTimeout = CommandTimeout; //wait time before terminating the attempt to execute a command and generating an error in secs

                        using (var da = new DB2DataAdapter(cmd))
                        {
                            da.Fill(DTT);
                        }
                        DTT.TableName = TableName;
                        return DTT;
                    }
                }
            }
            catch (Exception)
            {
                //LogManager.EventLog("[Error] Inside GetAssignedRolesForUser: " + ex.Message);
                throw;
            }
        }

调用 C# 函数的代码:

DataTable DtRoles = <Call function here>
                foreach (DataRow row in DtRoles.Rows)
                {
                    list.Add(Convert.ToInt32(row["ROLE_ID"].ToString()));
                }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多