C#里使用Oracle.DataAccess返回包里的记录集游标含Oralce里的分页包代码

今天用到C#里调用Oralce包里的SP返回分页的记录集,在网上查了一下,都用的是MS提供的Oracle.Cient,而在 Oracle.DataAccess.Client 里调用时(Ms的Oracle.Client 有问题,所以用的是Oracle官方提供的Oracle.DataAccess.Client ),输出的参数也要赋值后调用才能返回,否则返回的记录集是空的。即DbNull.Value要先赋值到参数上。

今天发现Oracle的Package确实不错,是我用的这几天里的我目前感觉到的一大亮点(可以重载,可以把相关的操作放到一个包里)。不知MSSQL2008里有没有。

C#里调用的代码如下:

[Test]    
public void Page1Test()    
{    
    using(Database db = DBFactory.Create())    
    {    
        const string sql = " select * from test_temp where ID < 1000 order by id asc ";    

        OracleCommand cmd = new OracleCommand("PAGESPLIT_PKG.PAGESPLIT_SP",db.Connection);    
        cmd.CommandType = CommandType.StoredProcedure;    
        OracleParameter p1 = new OracleParameter("pagesize", OracleDbType.Int32);    
        p1.Direction = ParameterDirection.Input;    
        p1.Value = 20;    
        OracleParameter p2 = new OracleParameter("pageindex", OracleDbType.Int32);    
        p2.Direction = ParameterDirection.Input;    
        p2.Value = 2;    
        OracleParameter p3 = new OracleParameter("sqltext", OracleDbType.Varchar2);    
        p3.Direction = ParameterDirection.Input;    
        p3.Value = sql;    
           
        OracleParameter p4 = new OracleParameter("Records_out", OracleDbType.Int32,DBNull.Value,ParameterDirection.Output); //就算是空值也要写,否则是会出错的    
        OracleParameter p5 = new OracleParameter("table_out", OracleDbType.RefCursor,DBNull.Value, ParameterDirection.Output);    
            
        cmd.Parameters.Add(p1);    
        cmd.Parameters.Add(p2);    
        cmd.Parameters.Add(p3);    
        cmd.Parameters.Add(p4);    
        cmd.Parameters.Add(p5);    

        OracleDataAdapter da = new OracleDataAdapter(cmd);    


        DataSet ds = new DataSet();    
        da.Fill(ds);    

        Console.WriteLine(ds.Tables.Count);    
        Console.WriteLine(ds.Tables[0].TableName);    
        Console.WriteLine(ds.Tables[0].Rows.Count);    
        Console.WriteLine("结果:" + cmd.Parameters["Records_out"].Value.ToString());    

        foreach(DataRow  row in ds.Tables[0].Rows)    
        {    
            Console.WriteLine(row[1]);    
        }    
    }    
} 

Oracle里分页包代码如下:

create or replace package PageSplit_PKG as   
-----------------------------------------------------------------------    
-- 分页模块PageSplitPackage4Oracle V0.01    
-- Author : zhouyu  Eamil:atwind@cszi.com    
-- 2009-11-4    
-----------------------------------------------------------------------/    
   
    type DataTable is REF CURSOR;  --游标类型定义,用于返回数据集    
        
    procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,Records_out out int,Table_out out DataTable); --申明包里的SP1    
        
    procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,Records_out out int,Pages_out out int,Table_out out DataTable); --申明包里的SP2    
        
    procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,SqlTextCount string,Records_out out int,Table_out out DataTable); --申明包里的SP3    
        
    procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,Table_out out DataTable); --申明包里的SP3    
        
end;    
   
create or replace package body PageSplit_PKG as   
        
-- 以下方法来自于网络修改    
--------------------------------------------------------------------------------------------    
--功能描述: 大数据量分页通用存储过程,超过100W数据的表,尽量加上索引上的条件    
--创建时间: 2009-11-4    
--------------------------------------------------------------------------------------------/    
    procedure PageSplit_SP    
    (    
        PageSize int,       --每页记录数    
        PageIndex int,         --当前页码,从 1 开始    
        SqlText string,     --查询语句,含排序部分    
        Records_out out int,--返回总记录数    
        Table_out out DataTable  ----返回当前页数据记录    
    ) as  --对包中定义的SP1的实现    
    v_sql varchar2(8000);  -- 不要超过32767个字符,不可以使用nvarchar2型,下面用的是to_char()    
    v_count int;    
    v_maxRownum int;    
    v_minRownum int;    
     begin   
        --取记录总数    
        v_sql := 'select count(*) from (' || SqlText || ')';    --拼接统计Sql    
        execute immediate v_sql into v_count; --执行统计    
        Records_out := v_count;    
            
         --行位置判断    
        v_maxRownum := PageIndex * PageSize;    
        v_minRownum := v_maxRownum - PageSize + 1;    
            
        --拼接查询语句    
        v_sql := 'SELECT *   
              FROM (   
                  SELECT A.*, rownum rn   
                  FROM  ('|| SqlText ||') A   
                  WHERE rownum <= '|| to_char(v_maxRownum) || '   
              ) B   
              WHERE rn >= ' || to_char(v_minRownum) ;    
              --注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn    
            
        open Table_out for  v_sql;    
   
     end;    
   
   
/**//*****************************************************************    
 *功能描述: 大数据量分页通用存储过程(重载1,直接返回分页数量)    
 *创建时间: 2009-11-3    
 *****************************************************************/    
    procedure PageSplit_SP    
    (    
        PageSize int,       --每页记录数    
        PageIndex int,         --当前页码,从 1 开始    
        SqlText string,     --查询语句,含排序部分    
        Records_out out int,--返回总记录数    
        Pages_out out int,  --返回分出的页数    
        Table_out out DataTable  ----返回当前页数据记录    
    )    
    as   
        v_sql varchar2(8000);    
        v_count int;    
        v_maxRownum int;    
        v_minRownum int;    
    begin   
      ----取记录总数    
      v_sql := 'select count(*) from (' || SqlText || ')';  --生成统计字符串    
      execute immediate v_sql into v_count; --执行统计    
      Records_out := v_count;    
          
      --行位置判断    
      v_maxRownum := PageIndex * PageSize;    
      v_minRownum := v_maxRownum - PageSize + 1;    
          
      --拼接查询语句    
      v_sql := 'SELECT *   
                FROM (   
                      SELECT A.*, rownum rn   
                      FROM  ('|| SqlText ||') A   
                      WHERE rownum <= '|| to_char(v_maxRownum) || '   
                     ) B   
                WHERE rn >= ' || to_char(v_minRownum) ;    
                --注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn    
   
        OPEN Table_out FOR  v_sql;    
   
    end;    
   
   
/**//*****************************************************************    
 *功能描述: 大数据量分页通用存储过程(重载2,自定义统计查询,推荐使用)    
 *创建时间: 2009-11-3    
 *****************************************************************/    
    procedure PageSplit_SP    
    (    
        PageSize int,        --每页记录数    
        PageIndex int,      --当前页码,从 1 开始    
        SqlText string,    --查询语句,含排序部分    
        SqlTextCount string,     --获取记录总数的查询语句    
        Records_out out int,    --返回总记录数    
        Table_out out DataTable)    
    as   
        v_sql varchar2(8000);    
        v_count int;    
        v_maxRownum int;    
        v_minRownum int;    
    begin   
      ----取记录总数    
      execute immediate SqlTextCount into v_count;    
      Records_out := v_count;    
      ----执行分页查询    
      v_maxRownum := PageIndex * PageSize;    
      v_minRownum := v_maxRownum - PageSize + 1;    
   
      v_sql := 'SELECT *   
                FROM (   
                      SELECT A.*, rownum rn   
                      FROM  ('|| SqlText ||') A   
                      WHERE rownum <= '|| to_char(v_maxRownum) || '   
                     ) B   
                WHERE rn >= ' || to_char(v_minRownum) ;    
                --注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn    
   
      OPEN Table_out FOR  v_sql;    
   
    end ;    
   
/**//*****************************************************************    
 *功能描述: 大数据量分页通用存储过程(重载3,不输出总记录数,适用于外部分页计算,内部直选记录集,DB计算压力最小)    
 *创建时间: 2009-11-3    
 *****************************************************************/    
    procedure PageSplit_SP    
    (    
        PageSize int,        --每页记录数    
        PageIndex int,      --当前页码,从 1 开始    
        SqlText string,  --查询语句,含排序部分    
        Table_out out DataTable    
    )    
    as   
        v_sql varchar2(8000);    
        v_maxRownum int;    
        v_minRownum int;    
    begin   
   
      ----执行分页查询    
      v_maxRownum := PageIndex * PageSize;    
      v_minRownum := v_maxRownum - PageSize + 1;    
   
      v_sql := 'SELECT *   
                FROM (   
                      SELECT A.*, rownum rn   
                      FROM  ('|| SqlText ||') A   
                      WHERE rownum <= '|| to_char(v_maxRownum) || '   
                     ) B   
                WHERE rn >= ' || to_char(v_minRownum) ;    
                --注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn    
   
      OPEN Table_out FOR  v_sql;    
   
    end;    
   
   
end;   

共有0个回答