有关.NET如何访问oracle数据库,在此就不介绍了。相关的资料也很多,有兴趣的朋友可以看下文。
使用ASP.NET访问Oracle数据库的方法
http://www.weiw.com/article/list.asp?id=649oracle的存储过程返回记录集,关键之处是要用游标。
关于数据库的游标(cursor)大家肯定都接触不少,我们可以通过OPEN,FETCH,CLOSE操作控制游标进行各种方便的操作,这方面的例子我就不在重复了。我们现在要介绍的是游标变量(cursor variable)。类似游标,游标变量也是指向一个查询结果集的当前行。不同的是,游标变量能为任何类型相似(type-compatible)的查询打开,而并不是绑定到某一个特定的查询。通过游标变量,你可以在数据库的数据提取中获得更多的方便。首先是建立表。CREATE TABLE LIHUAN.BILL_POINTS
(
    POINTS_ID                      NUMBER(10,0) NOT NULL,
    CUSTOMER_ID                    NUMBER(10,0) NOT NULL,
    BILL_POINT_NO                  NUMBER(2,0) DEFAULT 1 NOT NULL,
    CONSTRAINT PK_BILL_POINTS PRIMARY KEY (POINTS_ID)
)
/其次,建PACKAGE 
CREATE OR REPLACE PACKAGE LIHUAN.YY_PKG_BILL_POINT_NO/*取得用户的所有计费电序号*/
IS
TYPE T_CURSOR IS REF CURSOR;   PROCEDURE BILL_POINT_NO(P_CUSTOMER_ID BILL_POINTS.CUSTOMER_ID%TYPE,
   Re_CURSOR OUT T_CURSOR);
END;
/再次,建PACKAGE BODY
CREATE OR REPLACE PACKAGE BODY LIHUAN.YY_PKG_BILL_POINT_NO/*取得用户的所有计费电序号*/
IS PROCEDURE BILL_POINT_NO(P_CUSTOMER_ID BILL_POINTS.CUSTOMER_ID%TYPE,
   Re_CURSOR OUT T_CURSOR)
   IS
   V_CURSOR T_CURSOR; 
   BEGIN
      OPEN V_CURSOR FOR 
            select Bill_Point_No from BILL_POINTS where CUSTOMER_ID =P_CUSTOMER_ID;
           Re_CURSOR := V_CURSOR;
   END;
END;
/最后,在.NET中程序调用。
public DataSet Bill_Point_No(string CUSTOMER_ID)//ok
  {
   DataSet dataset = new DataSet();
   Hashtable HT=new Hashtable();
   HT.Add("P_CUSTOMER_ID",CUSTOMER_ID);
   if(RunProcedure("Re_CURSOR",OracleType.Cursor,ref dataset,HT,bmsOracleUser+".YY_PKG_BILL_POINT_NO.BILL_POINT_NO",bmsOracleConnectionString))
   {
    ;
   }
   else
   {
    dataset=null;
   }
   return dataset;
  }public bool RunProcedure(string ReturnParameter,OracleType ParamType,ref DataSet Dataset,Hashtable HT ,string ProcedureName,string OracleConnection) 
  { 
   System.Data.OracleClient.OracleConnection dsconnection = new System.Data.OracleClient.OracleConnection(OracleConnection);
   System.Data.OracleClient.OracleCommand dacommand = new System.Data.OracleClient.OracleCommand(ProcedureName,dsconnection);
   dsconnection.Open(); 
   dacommand.CommandType=CommandType.StoredProcedure;
   IDictionaryEnumerator Enumerator;
   Enumerator = HT.GetEnumerator();
   object Value=null;
   OracleParameter OracleParam;
   OracleParam = dacommand.Parameters.Add(new OracleParameter(ReturnParameter,ParamType));
   OracleParam.Direction = ParameterDirection.Output;
   while(Enumerator.MoveNext())
   {
    Value = Enumerator.Value;
    OracleParam=dacommand.Parameters.Add(new OracleParameter(Enumerator.Key.ToString(), Value));
   }
   OracleDataAdapter ODAdapter=new OracleDataAdapter(dacommand);
            try
   {
    ODAdapter.Fill(Dataset);
     return true;
   }
   catch(System.Exception e)
   {
    e.ToString();
    return false;
   }
   finally
   {   
    HT.Clear();
    dacommand.Parameters.Clear();
    dsconnection.Close();
   }
 }

解决方案 »

  1.   

    to wangj2001(乡村酒吧) ,我刚起步Oracle,为什么调用存储过程,一定要用在Package中?我做SQL Server2000的时候好像没有这么复杂的,甚至现在有很多我都是先写成SQL Server2000的样子,然后根据语法翻译,呵呵,能否解释一下为什么调用存储过程,一定要用在Package中?另外,能否给个简单的就是我的那个样式结构的存储过程?谢谢!
      

  2.   

    oracel和sqlserver不一样,sqlserver做起来非常方便,可以等我晚上到家以后帮你看吗?有事给我邮件[email protected]
      

  3.   

    package可以用来定义记录集(不太准确,说明问题就行),这里不用cursor和package,不过你熟悉以后会发现他们的好处。
    存储过程结构如下:
    Create or Replace Procedure xx_yy
    (
        i_OrderID in number,
        i_ReturnValue out number
    )
    is
        v_RealValue number;
        v_TotalValue number;
        v_AdvendorID  number;
    begin
       自己写就行
    end;
    下面讲一下调用:表结构
    create table ORDERTABLE
    (
      ORDERID NUMBER not null,
      TEXT    NUMBER not null
    )
    存储过程  (
        i_OrderID in number,
        i_ReturnValue out number
    )
    is
      spass ordertable.text%type;
    begin
      select text into spass from ordertable where orderid=i_OrderID; 
      i_ReturnValue:=spass;
      exception
       when no_data_found
       then i_ReturnValue:=-1; 
    end;源码:
    using System.Data .OracleClient ;//(别忘了添加)
    OracleConnection  Oraclecon = new OracleConnection ("Password=dloco;User ID=dloco;Data Source=dloco;");
    OracleCommand myCMD =  new OracleCommand();
    OracleParameter[] parameters = { new OracleParameter("i_OrderID", OracleType.Number, 10),new OracleParameter("i_ReturnValue",OracleType.Number,10 )};
    parameters[0].Value = 1;
    parameters[1].Direction = ParameterDirection.Output; myCMD.Connection = Oraclecon;
    myCMD.CommandType = CommandType.StoredProcedure;
    myCMD.CommandText = "dloco.xx_yy"; myCMD.Parameters .Add (parameters[0]);
    myCMD.Parameters .Add (parameters[1]); myCMD.Connection.Open(); myCMD.ExecuteNonQuery();     

    string result=myCMD.Parameters["i_ReturnValue"].Value.ToString();
    MessageBox.Show (result); Oraclecon.Close();如还有不明白,继续问
      

  4.   

    上面的帖子像package可以用来定义记录集(不太准确,说明问题就行),这里不用cursor和package,不过你熟悉以后会发现他们的好处。
    存储过程结构如下:
    Create or Replace Procedure xx_yy
    (
        i_OrderID in number,
        i_ReturnValue out number
    )
    is
        v_RealValue number;
        v_TotalValue number;
        v_AdvendorID  number;
    begin
       自己写就行
    end;
    下面讲一下调用:是废话不用看
      

  5.   

    再问一个小问题结贴,我发现Oracle中定义的变量有的是数据库中表的字段后边加%type,这个是怎么回事?
    比如: table tableA(field1 varchar)
    produce中:a field1%type;解释一下
    另外我在调用存储过程的时候,我以前用sql=@"exec ProdueceName '"+parm+""";,但在Oracle中这种方式调用一直不对,为什么?
      

  6.   

    %TYPE
    如果我们声明一个变量,并且希望改变量和数据库中的某一列的数据类型和长度都相同的话,就需要用到%TYPE类型。%TYPE可以保证定义的变量的数据类型和长度与数据库表中对应地保持一致,即使数据库表中的纪录的数据类型或长度发生变化,也可以保持一致。明白没有
      

  7.   

    EXEC PROCEDURE_NAME(PARAMETER);第二个问题