我们知道,Microsoft patterns & practices小组开发的Enterprise Library是一款非常好的组件,其有很多个模块,包括数据访问、配置、加密、IOC容器、日志、异常处理等内容,其中数据访问模块是其中非常不错的一个数据访问组件,提供了对各种数据库操作的抽象封装,使用数据访问起来基本上是对各种数据库是透明的,最重要的是,简化了代码,提高了开发效率。
本文介绍Enterprise Library中的数据访问模块在操作Oracle过程中的一些经验总结,作为自己和博友做数据库访问的一个参考。
1、存储过程的游标处理
这个和SqlServer数据获取有点不同,在Oracle中用存储过程返回数据内容,必须定义一个游标,如下面所示的Oracle存储过程
------------------------------------
--Author:伍华聪
--Create time:2009-08-21
--Description:创建一个包,含有一个游标类型:(一个数据库中只需作一次)
------------------------------------
CREATE OR REPLACE PACKAGE MyCURSOR
AS
TYPE cur_OUT IS REF CURSOR;
End;
/
------------------------------------
--Author:伍华聪
--Create time:2009-08-21
--Description:检索表中所有的数据
------------------------------------
Create Or Replace Procedure WUHUACONG.PUB_PHONE_SelectAll
( cur_OUT OUT MyCURSOR.cur_OUT )
AS
Begin
OPEN cur_OUT FOR Select * from GIS.PUB_PHONE;
End;
/
------------------------------------
--Author:伍华聪
--Create time:2009-08-21
--Description:以字段COMPANYID为关键字,检索表中的数据
------------------------------------
Create Or Replace Procedure WUHUACONG.PUB_PHONE_SelectByCOMPANYID
(
cur_OUT OUT MyCURSOR.cur_OUT ,
p_COMPANYID IN GIS.PUB_PHONE.COMPANYID%TYPE
)
AS
Begin
OPEN cur_OUT FOR Select * from GIS.PUB_PHONE Where COMPANYID = p_COMPANYID ;
End;
/
大家看到,上面的SelectAll和SelectBy存储过程都需要一个游标的参数,是OUT类型的,也就是你获取数据需要定义一个输出的游标参数,我们看看普通的数据访问是如何做的。
List<LeagueCompany> list = new List<LeagueCompany>();
try
{
using (OracleConnection con = new OracleConnection("Data Source=DEVBAK;user=WUHUACONG;password=WUHUACONG;"))
{
OracleCommand cmd = new OracleCommand();
cmd.Connection = con;
cmd.Parameters.Add("cur_OUT", OracleType.Cursor).Direction = ParameterDirection.Output;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "PUBDB.sp_LeagueCompanyInit";
cmd.Connection.Open();
OracleDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
#region 解析字段内容
LeagueCompany c = new LeagueCompany();
if (reader["companyid"] != DBNull.Value)
{
c.CompanyId = int.Parse(reader["companyid"].ToString());
}
if (reader["companyname"] != DBNull.Value)
{
c.CompanyName = reader["companyname"].ToString();
}
if (reader["mainid"] != DBNull.Value)
{
c.MainId = int.Parse(reader["mainid"].ToString());
}
if (reader["subid"] != DBNull.Value)
{
c.SubId = int.Parse(reader["subid"].ToString());
}
if (reader["teamid"] != DBNull.Value)
{
c.TeamId = int.Parse(reader["teamid"].ToString());
}
if (reader["levelid"] != DBNull.Value)
{
c.Level = int.Parse(reader["levelid"].ToString());
}
#endregion
list.Add(c);
}
}
}
}
catch (Exception ex)
{
LogHelper.Error(ex);
MessageBox.Show(string.Format("获取公司列表异常->" + ex.Message));
}
this.dataGridView1.DataSource = list;
}
上面是不用Enterprise Library数据访问而直接使用ADO.NET的数据对象访问的数据库,可以看到存在两个问题,一个是数据操作的代码比较臃肿,如果你使用很多这种操作,就会发现很多重复性的代码,另外就是数据解析的部分也比较臃肿重复,我们下面看看使用了Enterprise Library数据访问模块后的效果是如何。
//Database db = DatabaseFactory.CreateDatabase();//通过Web.Config或者*.exe.Config配置文件读取
Database db = new OracleDatabase("Data Source=DEVBAK;user=WUHUACONG;password=WUHUACONG;");//直接传递连接字符串,适合自定义配置文件的处理
string sqlCommand = "PUBDB.sp_LeagueCompanyInit";
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
//由于EnterpriseLibrary 默认的数据访问游标是cur_OUT,所以下面可以省略
//OracleParameter cursorParam = new OracleParameter("cur_OUT", OracleType.Cursor);
//cursorParam.Direction = ParameterDirection.Output;
//dbCommand.Parameters.Add(cursorParam);
List<LeagueCompany> list = new List<LeagueCompany>();
try
{
using (IDataReader dr = db.ExecuteReader(dbCommand))
{
while (dr.Read())
{
#region 解析字段内容
SmartDataReader reader = new SmartDataReader(dr);
LeagueCompany c = new LeagueCompany();
c.CompanyId = reader.GetInt("companyid");
c.CompanyName = reader.GetString("companyname");
c.MainId = reader.GetInt("mainid");
c.SubId = reader.GetInt("subid");
c.TeamId = reader.GetInt("teamid");
c.Level = reader.GetInt("levelid");
#endregion
list.Add(c);
}
}
}
catch (Exception ex)
{
LogHelper.Error(ex);
MessageBox.Show(string.Format("获取公司列表异常->" + ex.Message));
}
this.dataGridView1.DataSource = list;
是不是代码很简短了,这里注意两个地方,一个是我们创建游标的时候,采用cur_OUT来做为它的名称,这样我们就不用增加整个游标的定义了,因为EnterpriseLibrary模块默认给我们增加了这个游标处理(有可以少3行代码了)。另外引入了SmartDataReader对象来处理数据的转换问题,这个类后面附上,以供参考。
由于EnterpriseLibrary 默认的数据访问游标是cur_OUT,如果存储过程的游标名称和cur_OUT不一样,如p_Cur,那么数据库操作代码会变化为下面,这个必须注意。否则你的数据访问总是获取不到而发生错误。
Database db = new OracleDatabase("Data Source=DEVBAK;user=WUHUACONG;password=WUHUACONG;");//直接传递连接字符串,适合自定义配置文件的处理
string sqlCommand = "PUBDB.sp_LeagueCompanyInit";
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
OracleParameter cursorParam = new OracleParameter("p_Cur", OracleType.Cursor);
cursorParam.Direction = ParameterDirection.Output;
dbCommand.Parameters.Add(cursorParam);
List<LeagueCompany> list = new List<LeagueCompany>();
try
{
using (IDataReader dr = db.ExecuteReader(dbCommand))
{
while (dr.Read())
{
}
}
}
catch (Exception ex)
{
LogHelper.Error(ex);
MessageBox.Show(string.Format("获取公司列表异常->" + ex.Message));
}
下面附上数据解析类的代码,供参考。
http://files.cnblogs.com/wuhuacong/SmartDataReader.rar
本文转自博客园伍华聪的博客,原文链接:使用Enterprise Library操作Oracle的疑点难点总结,如需转载请自行联系原博主。