zoukankan      html  css  js  c++  java
  • ado.net之SQLServer和Oracle (sys_cursor) 数据库链接——获取结果集方式对比

    ADO链接:SQLServer与Oracle,重点是在获取多行多列的结果集方式上不同:

    链接Oracle时,需要以ref游标的方式获取结果集(数据库端必须编写package或者procedure,并且返回ref游标,ADO数据链接程序则需要定义一个OracleDbType.RefCursor类型的参数,接收数据库端的指向结果集的ref游标),而链接SQLServer时,没有这一要求。

    数据库链接方法被封装在SqlHelper类中:

    using System.Data;
    using Oracle.ManagedDataAccess.Client;
    
    namespace DAL
    {
        public class SqlHelper
        {
            //数据库连接字符串
            //SqlServer
            private static string ConnString = "Server=.;DataBase=HotelDB;Uid=sa;Pwd=sj123";
            //Oracle
            //private static string ConnString = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=sajet1)));Persist Security Info=True;User ID=sajet;Password=tech;";
            //这里只展示获取结果集的方法,其他方法不展示
            public static OracleDataReader GetResult(string sql,OracleParameter[] param,bool flag)
            {
                OracleConnection conn = new OracleConnection(connString);
                OracleCommand cmd = new OracleCommand(sql, conn);
                if (flag)
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                }
                if (param != null)
                {
                    cmd.Parameters.AddRange(param);
                }
                try
                {
                    conn.Open();
                    return cmd.ExecuteReader(CommandBehavior.CloseConnection);
                }
                catch (Exception ex)
                {
                    conn.Close();
                    throw ex;
                }
            }
        }
    }
    View Code

    DishService.cs :调用SQLHelper类,负责数据的传递(接收应用程序的数据并上传数据库,或将数据库的数据取出来返回给应用程序)

    [这里以DishService类为例,可以改成任意类]

    SQLServer:不需要引用外部的dll

    public List<DishCategory> GetDishCategories()
    {
        string sql = "select CategoryId,CategoryName from dishcategory";
        SqlDataReader objReader = SqlHelper.GetResult(sql);
        List<DishCategory> dishList = new List<DishCategory>();
        while(objReader.Read())
        {
            dishList.Add(new DishCategory()
            {
                CategoryId = Convert.ToInt32(objReader["CategoryId"]),
                CategoryName = objReader["CategoryName"].ToString()
            });
        }
        objReader.Close();
        return dishList;
    }

    上面的sql语句也能以存储过程的方式写到SQLServer上:

    use HotelDB
    go
    if exists(select * from sysobjects where name='usp_GetAllDishCategory')
    drop procedure usp_GetAllDishCategory
    go
    create procedure usp_GetAllDishCategory
    as
    begin
        select categoryid,categoryname from DishCategory
        --这里返回一张表的结果集
    end
    go

    ADO方法调用上面的存储过程:

    public List<DishCategory> GetDishCategories()
    {
        SqlDataReader objReader = SqlHelper.GetResult("usp_GetAllDishCategory",null,true);
        List<DishCategory> dishList = new List<DishCategory>();
        while(objReader.Read())
        {
            dishList.Add(new DishCategory()
            {
                CategoryId = Convert.ToInt32(objReader["CategoryId"]),
                CategoryName = objReader["CategoryName"].ToString()
            });
        }
        objReader.Close();
        return dishList;
    }

    Oracle:需要引用外部的dll(这里用的是Oracle.ManagedDataAccess.dll)

    要获取结果集,必须编写存储过程,返回指向结果集的引用游标。[Oracle提供REF CURSOR,通过引用游标可以实现在程序间传递结果集的功能]

    CREATE OR REPLACE procedure SAJET.usp_GetAllDishCatetory
    (
        dish_cur out sys_refcursor
    )
    is
    begin
         --返回指向结果集的游标   
        open dish_cur for select CategoryId,CategoryName from DishCategory;
        --close dish_cur;这里千万不能画蛇添足,不能关闭游标,否则数据库将释放游标指向的内存空间,ado的OracleCommand类的ExecuteReader()方法接收不到任何数据。
    end usp_GetAllDishCatetory;

    ADO方法调用上面的存储过程:

    public List<DishCategory> GetDishCategories()
    {
        OracleParameter cur_result = new OracleParameter(":dish_cur", OracleDbType.RefCursor);
        //默认输入参数不需要指明指向类型,如果是输出参数需要指明参数指向类型
        cur_result.Direction = ParameterDirection.Output;
        OracleParameter[] param = new OracleParameter[] { cur_result }; 
        OracleDataReader objReader = SqlHelper.GetResult("SAJET.usp_GetAllDishCatetory",param,true);
        List<DishCategory> dishList = new List<DishCategory>();
        while (objReader.Read())
        {
            dishList.Add(new DishCategory()
            {
                CategoryId = Convert.ToInt32(objReader["CategoryId"]),
                CategoryName = objReader["CategoryName"].ToString()
            });
        }
        objReader.Close();
        return dishList;
    }

    补充:应用程序中如何释放数据库资源?

    关闭数据库连接对象--->数据库连接一旦显式关闭,那么这个连接进程会在服务器端也进行强制挂起,并进入关闭的队列,等待关闭。[所以不用担心数据库端的游标不会被关闭]

    这里要强调的是,XXXDataReader在获取数据的时候,应用程序与数据库的连接不会被断开,但数据被取完后,需要关闭读取器。

    原理:应用程序发现读取器关闭后

    objReader.Close();

    读取器对象会通过下面的方式:

    cmd.ExecuteReader(CommandBehavior.CloseConnection);

    触发数据库连接对象conn.Close()方法。

  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/pandora2050/p/15134277.html
Copyright © 2011-2022 走看看