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()方法。

  • 相关阅读:
    ajax理论
    模块
    node.js(1)
    ES6
    data对象
    数组
    对象
    webdriver对应的驱动版本
    TrineaAndroidCommon API Guide
    PV,UV,IP概念
  • 原文地址:https://www.cnblogs.com/pandora2050/p/15134277.html
Copyright © 2011-2022 走看看