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; } } } }
DishService.cs :调用SQLHelper类,负责数据的传递(接收应用程序的数据并上传数据库,或将数据库的数据取出来返回给应用程序)
[这里以DishService类为例,可以改成任意类]
SQLServer:
public List<DishCategory> GetDishCategories() { string sql = "select CategoryId,CategoryName from dishcategory"; OracleDataReader 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() { OracleDataReader 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:
要获取结果集,必须编写存储过程,返回指向结果集的引用游标。[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()方法。