读书人

新手请问几个.Net数据库的有关问题

发布时间: 2012-01-28 22:06:14 作者: rapoo

新手请教几个.Net数据库的问题
刚转到.Net平台下面来,多多不适应,向大家讨教几个问题
1、以前用VB6写数据库相关程序都是做一个全局Connection数据库连接对象,程序开始的时候打开连接,程序退出的时候关闭连接。在.Net下面不知道这种做法是否合适?是否一般都把数据库连接对象作为静态变量?提出这个问题主要是最近使用sqlDataReader对象来操作数据库,只要有超过两个sqlDataReader对象就会报错:“已有打开的与此命令相关联的 DataReader,必须首先将它关闭”。网上查看了一些帖子,都说一个Connection对象不能同时用在两个sqlDataReader对象中,如果是这样的话难道每个操作都要打开、关闭数据库连接,难道打开关闭数据库连接这个操作不需要时间开销吗?这样难道不会影响效率?
2、sqlDataReader对象是一个轻量级的数据读取对象,较sqlDataSet是否效率好一些?但是sqlDataset似乎可以在不关闭连接对象的情况下创建任意多个sqlDataset对象,相比sqlDataReader每个对象都要创建连接对象是否更适合在一个过程内频繁访问数据库?

[解决办法]
1.差不多吧。可以看下sqlhelper.另外vs下有很多更先进的方法,建议你体验下。
2.用法不一样的,不是大小的区别。dataset是把所有结果装入到内存中,不适合大量数据,比如上万的。datareader是一条一条的读,所以需要和数据库保持连接。跟recordset差不多,只不过它只能向后读。
[解决办法]
...你喜欢怎么写就怎么写呗
轻量级的你嫌关闭数据库麻烦就用USING(){}
适用完后会自动释放掉。
你如果考虑性能,用连接池。
[解决办法]
(一).说明

初学ADO.Net会被ADO.Net访问数据库方式弄得头晕,感觉无从下手.
本文将它们整合在一起,文章并没有涉及太多深层知识. 只是我觉得将它们集中在一起,
在比较中学习更快,更清晰一些:
本文列举了用ADO.Net访问数据库的所有方式:
1.用Sql语句访问数据库
2.用无参存储过程访问数据库
3.用有参存储过程访问数据库
4.使用 CommandBuilder.DeriveParameters 来填充 Command 对象的 Parameters 集合,来访问数据库
5.使用SqlDataReader对象输出数据.

(二).代码示例

用到的存储过程 myprocedure SQL代码:
---有参

CREATE procedure dbo.[myprocedure]
(
@start int,
@end int
)
as
select * from products
where productid>=@start and productid<=@end

---无参
CREATE procedure dbo.[myprocedure]
as
return 'Hello'
GO



private DataSet GetDataSet(int sign)
{

//*******自定义连接字符串********/
string connectionStr="server=(localhost);uid=sa;pwd=;database=NorthWind";

SqlConnection myConnection=new SqlConnection(connectionStr);
DataSet myDataSet=new DataSet();
string sqlProcedureName="myprocedure"; //此存储过程必须事先已经定义好了.
if(sign==1)//执行语句. (最常用的情况)

{
string queryStr="select * from products";
SqlDataAdapter myAdapter=new SqlDataAdapter(queryStr,connectionStr);

myAdapter.Fill(myDataSet);
return myDataSet;
}


if(sign==2)//调用SQL无参存储过程,此存储过程返回select查询结果
{
SqlCommand myCommand=new SqlCommand(sqlProcedureName,myConnection);
myCommand.CommandType=CommandType.StoredProcedure;
SqlDataAdapter myAdapter=new SqlDataAdapter(sqlProcedureName,myConnection);
myAdapter.Fill(myDataSet);
return myDataSet;
}
if(sign==3)//调用SQL有参存储过程,此存储过程返回select查询结果,且传递参数
{
SqlCommand myCommand=new SqlCommand(sqlProcedureName,myConnection);
myCommand.CommandType=CommandType.StoredProcedure;

SqlParameter start=new SqlParameter("@start",SqlDbType.Int,4); // 定义第一个参数

start.Value=1;
myCommand.Parameters.Add(start);

SqlParameter end=new SqlParameter("@end",SqlDbType.Int,4); // 定义第二个参数

end.Value=5;
myCommand.Parameters.Add(end);

SqlDataAdapter myAdapter=new SqlDataAdapter(sqlProcedureName,myConnection);
myAdapter.SelectCommand=myCommand;

myAdapter.Fill(myDataSet);
return myDataSet;
}
if(sign==4) //演示如何使用 CommandBuilder.DeriveParameters 来填充 Command 对象的 Parameters 集合
{
SqlCommand myCommand=new SqlCommand(sqlProcedureName,myConnection);
myCommand.CommandType=CommandType.StoredProcedure;
SqlDataAdapter myAdapter=new SqlDataAdapter(sqlProcedureName,myConnection);

myConnection.Open(); //如果不打开连接,下一句将不知道从哪里去取所需的存储过程
SqlCommandBuilder.DeriveParameters(myCommand);
myCommand.Parameters["@start"].Value=1;


myCommand.Parameters["@end"].Value=5;
myAdapter.SelectCommand=myCommand;

myAdapter.Fill(myDataSet);
return myDataSet;

}
if(sign==5)//练习使用SqlDataReader,结果在控制台输出
{
SqlCommand myCommand=new SqlCommand(sqlProcedureName,myConnection);
myCommand.CommandType=CommandType.StoredProcedure;

SqlParameter start=new SqlParameter("@start",SqlDbType.Int,4); // 把4改变或去掉
start.Value=1;
myCommand.Parameters.Add(start);

SqlParameter end=new SqlParameter("@end",SqlDbType.Int,4); // 把4改变或去掉
end.Value=5;
myCommand.Parameters.Add(end);

SqlDataAdapter myAdapter=new SqlDataAdapter(sqlProcedureName,myConnection);
myAdapter.SelectCommand=myCommand;

myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader();

Console.WriteLine("{0}, {1}", myReader.GetName(0), myReader.GetName(1));

while (myReader.Read())
{
//Console.WriteLine("{0},{1}", myReader.GetString(0), myReader.GetString(1)); //?不对
Console.WriteLine("{0},{1}", myReader.GetValue(0), myReader.GetValue(1));
}

myConnection.Close();
DataTable myTable=new DataTable();
myDataSet.Tables.Add(myTable);
return myDataSet;
}
return new DataSet();
}


[解决办法]
http://blog.csdn.net/ChengKing/archive/2005/10/27/518079.aspx

(六).ADO.Net使用方面优化
1.数据库连接打开和关闭。 在需要连接时打开,当访问完数据库要立刻关闭连接.
举例说明,还是看两个代码段:

I.
DataSet ds = new DataSet();
SqlConnection MyConnection = new SqlConnection("server=localhost; uid=sa; pwd=; database=NorthWind");
SqlCommand myCommand = new SqlCommand(strSql,MyConnection);
SqlDataAdapter myAdapter=new SqlDataAdapter(queryStr,connectionStr);
MyConnection.Open(); //打开连接
for(int i=0;i<1000;i++) //for循环模拟取得数据前的商业逻辑操作
{
Thread.Sleep(1000);
}
myAdapter.Fill(ds);
for(int i=0;i<1000;i++) //for循环模拟取得数据后的商业逻辑操作
{
Thread.Sleep(1000);
}
MyConnection.Close(); //关闭连接
II.
DataSet ds = new DataSet();
SqlConnection MyConnection = new SqlConnection("server=localhost; uid=sa; pwd=; database=NorthWind");
SqlCommand myCommand = new SqlCommand(strSql,MyConnection);
SqlDataAdapter myAdapter=new SqlDataAdapter(queryStr,connectionStr);
for(int i=0;i<1000;i++) //for循环模拟取得数据前的商业逻辑操作
{
Thread.Sleep(1000);
}
MyConnection.Open(); //打开连接
myAdapter.Fill(ds);
MyConnection.Close(); //关闭连接
for(int i=0;i<1000;i++) ////for循环模拟取得数据后的商业逻辑操作
{
Thread.Sleep(1000);
}
显示II代码比I代码好的多,I中早早占着连接不放,如果用户很多的话,容易出现连接池满情况。严重时出现死机现象.
2.数据库查询
I. 直接生成SQL语句。 Sql Server每次都要对其进行编译,在性能方面不会有很大的提高。 另外也不够安全。容易被攻击.
II. 使用带参数的SQL命令。这种方式Sql Server只对其编译一次,对于不同的参数可以重复使用编译后的命令。提高了性能.
III.使用Sql Server存储过程. 编译一次. 具有独立性,便于修改和维护. 一次能完成用语句发送多次的功能.减少了网络的
流量。 并不一定存储过程一定比语句效率要高,如果商业逻辑很复杂的话,有时候用语句比存储过程效率要高.

[解决办法]

1.没见过用静态的SqlConnection
2.不会,尽管用吧
3.一般都写一个操作数据库的类 方便
优化查询吧

[解决办法]
写一个数据库操作类,要带参数,调用类的时候把sql命令作为string型参数传递,打开和关闭连接的语句全都包含在数据库操作类里就OK。用完sqldatareader要关闭。
------解决方案--------------------


1.在ADO.NET的思想里面连接存在的时间越短越好,所以每次使用sqlDataReader必须显示打开连接,填充数据后关闭连接。频繁打开关闭连接所造成的效率问题,ADO.NET用连接池解决。在连接字符串中,默认是打开连接池的
ADO.NET中的连接池
? 如果使用的是OleDBConnection类,则连接池有提供程序自动处理,您不必自己进行管理。
?如果使用的是sqlConnection类,则连接池被隐式管理,但也提供管理选项允许您自己管理池。
-在连接字符串中指定:
? pooling=true;//默认为true
? connection lifetime =5//默认为0
? min pool size =1//默认为0
? max pool size =50//默认为100
如果你是连接同一个数据库的话不需要重复new Connection ,new一个就好了 需要连数据库的时候Open()是不是耗时自己试试不就知道了吗,因为没用过vb不知道怎么比较。另外说下在ADO.NET 2.0中的DataSet的效率是ADO.NET1.X的40倍+。感觉vb好像很古董。
2.sqlDataReader与DataSet时两个层次的概念。DataReader可以叫数据阅读器它和DataAdapter的作用类似都是数据提供者的范畴。好像无sqlDataSet,应该是DataSet它是内存中的表,为XML格式。.net应用程序实质上绝大多数数据库操作的是它。
就我目前的理解是否频繁访问数据库和是否使用DataSet关系不大,关键是使用好连接池。
[解决办法]
数据库的确很烦。。。

读书人网 >C#

热点推荐