在C#中调用参数化存储过程,通过游标返回值并将其存储在DataTable中

时间:2018-05-03 08:04:43

标签: c# stored-procedures datatable parameters db2

我有一个存储过程通过游标运行select查询并返回游标(原始Select查询更复杂,我已经缩短了它。)

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;
  }
}

2 个答案:

答案 0 :(得分:1)

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

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

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

  

\ program files \ ibm \ sqllib \ samples \ dotnet \ cs

)然后你可以在那里看到C#的DataTable示例,也可以在知识中心 - " DbDatMap.cs"和相关文件和" SpClient.cs"及其依赖

请检查您填充DataTable DTreturn DTT

的原因

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

使用大多数语法的consoleApp对我来说很好,唯一的变化就是我使用了预先存在的连接,并为我的存储过程提供了varchar参数而不是整数(但这没有什么区别)。 / p>

答案 1 :(得分:1)

所以我终于开始工作了。关于开放游标,显然是在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()));
                }