ADO.NET的记忆碎片(二)

本文探讨了ADO.NET中Command类执行多条SQL语句并利用StatementCompleted事件获取每条语句影响的行数的方法。同时介绍了DataReader类的使用技巧,包括如何获取结果集的字段信息、使用强类型的getter提高性能以及处理多个结果集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接着 ADO.NET的记忆碎片(一)继续
Command类在执行SQL的时候,可能会遇到一次执行多条SQL的情况,就像这样:

string strConn ="...";//连接字符串
string strSql = "update tableName1 set...;"+"update tableName2 set...;";
SqlConnection cn = new SqlConnection(strConn);
cn.Open();
SqlCommand cmd = new SqlCommand(strSql,cn);
int intTotalRowsAffected = cmd.ExecuteNonQuery();//返回的是多条SQl语句影响的总行数

可以看到返回的是影响数据库表的总行数,这并不是我们想要的结果,解决的方法是在每次执行一条SQL语句完成的时候就能返回一个数据给我,这才是我想的。好在ADO.NET2.0提供了我们这样的获取机会,在Command中公开了一个StatementCompleted事件,这个事件是在每一条SQL语句执行完成后促发的,并且事件的主要参数中提供了RecordCount属性,就是表示这次SQL语句的执行对数据库表所产生的行数的影响。实现该功能如下:

string strConn ="...";//连接字符串
string strSql = "update tableName1 set...;"+"update tableName2 set...;";
SqlConnection cn = new SqlConnection(strConn);
cn.Open();
SqlCommand cmd = new SqlCommand(strSql,cn);
cmd.StatementCompleted += new StatementCompletedEventHandler(HandleStatementCompleted);
int intTotalRowsAffected = cmd.ExecuteNonQuery();//返回的是多条SQl语句影响的总行数
cn.Close();
...
static void HandleStatementCompleted( object sender, StatementCompletedEventArgs e)
{
Console.WriteLine(e.RecordCount);
}

DataReader类

前面其实已经多次使用了DataReader,在此做一回顾:
当一个Command对象执行ExecuteReader()方法返回值就是一个DataReader类型的实例,保存着查询的结果集。代码如下:

SqlDataReader rdr = cmd.ExecuteReader();

对查询的结果集遍历:

while(rdr.Read())
{
Console.WriteLine("{0}--{1}",rdr[0],rdr["CustomerName"]);
}
rdr.Close();

好了,下面对DataReader类进行进一步的研究,很多时候我们得到结果集,但是想看看里面的字段的数目、字段名称、字段的Net类型、字段的数据库数据类型等,这一些架构信息可以帮助我们更好的扩展应用程序,ADO.NET也帮助我们实现了方法我们可以自由的调用:

for(int intField=0;intField<rdr.FieldCount;intField++)//FieldCount是读取字段数量的属性
{
Console.WriteLine(intField);
Console.WriteLine(rdr.GetName(intField));//获取字段名称,参数是该字段的索引
Console.WriteLine(rdr.GetFieldType(intField).Name);//获取net数据类型,参数是该字段的索引
Console.WriteLine(rdr.GetDataTypeName(intField));//获取数据库数据类型,参数是该字段的索引
Console.WriteLine();
}
rdr.Close();

知道了字段名称怎么确定字段的索引,可以使用GetOrdinal()方法:

int fieldInt = rdr.GetOrdinal("CustomerName");//返回CustomerName这个字段的索引

用基于序号的查阅字段内容比基于字段名称查阅性能好,所有就是因为这个原因有时候GetOrdinal()是非常受欢迎的。
原来是:

while(rdr.Read())
{
Console.WriteLine("{0}--{1}",rdr[0],rdr["CustomerName"]);
}
rdr.Close();

可以改成:

int fieldInt = rdr.GetOrdinal("CustomerName");
while(rdr.Read())
{
Console.WriteLine("{0}",rdr[fieldInt]);
}
rdr.Close();

这样性能就可以得到提升,其实这段代码的性能还可以进一步的提升。

强类型的getter

其实目前我们使用的rdr[0]基于索引的取值,其实是返回一个object类型的数值,但是我们本来的字段的类型是多样的,有:int,string,datetime等,这样其实里面会有一个类型转换的问题,术语是会“装箱”和“拆箱”,这是很影响性能的,解决的办法就是使用强类型的getter,里面定义了许多net数据类型的公开Get(),如:GetString(),GetInt32() ,GetDateTime().代码可以改变如下:

int fieldInt = rdr.GetOrdinal("CustomerName");
while(rdr.Read())
{
Console.WriteLine("{0}",rdr.GetString(fieldInt));
}
rdr.Close();

在开发过程中,如果不能确定字段的类型,请尝试调用GetFieldType().
处理来自查询的多个结果集
很多时候我们一次查询会返回多个select结果,但是用DataRead实例中的Read()方法只能访问第一个结果集,要访问其他的结果集要调用NextResult()方法。代码:

do
{
while(rdr.Read())
{
Console.WriteLine("{0}",rdr.GetString(fieldInt));
}
} while(rdr.NextResult());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值