[转载]如何正确使用SqlConnection – LoveJenny – 博客园.
以前曾见过有人这样写代码:
public class Service1 : IService1{private SqlConnection conn = new SqlConnection();public void Method1(){//do something with conn;
}public void Method2(){//do something with conn;
}public void Method3(){//do something with conn;
}public void Method4(){//do something with conn;
}}在服务类中,新建一个全局的conn对象,然后使用conn对象来操作数据库。
当然,还有一些不同的版本,比如:
private SqlConnection conn = new SqlConnection();private static SqlConnection sconn = new SqlConnection();private SqlConnection Conn
{get { return new SqlConnection(); }}如果有人问你哪种方式比较好,你会怎么回答?
首先验证下在多线程环境下使用一个Connection的方式:
创建控制台程序:
Main代码如下:
public static void Main(){string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=""E:\DB\NORTHWND.mdf"";Integrated Security=True;Connect Timeout=30;User Instance=True";string connectionStringNoPooling = connectionString + " ;Pooling='false' ";SqlConnection conn = new SqlConnection(connectionString);
new Thread(() => { ExecuteCommand(conn); }) { Name = "t1" }.Start();new Thread(() => { ExecuteCommand(conn); }) { Name = "t2" }.Start();}public static void ExecuteCommand(SqlConnection conn){Console.WriteLine("Thread:{0},{1}", Thread.CurrentThread.Name, DateTime.Now);
conn.Open();SqlCommand command = new SqlCommand("select * from customers", conn);command.ExecuteNonQuery();command.Dispose();Thread.Sleep(5000); //模拟耗时的查询
conn.Close();Console.WriteLine("Thread:{0} 执行完毕,{1}", Thread.CurrentThread.Name, DateTime.Now);
}代码很简单,模拟两个线程同时执行ExecuteCommand.方法。结果如下:
可以知道在多线程环境下使用一个Connection来执行SQL语句是不安全的,
修改Main函数如下:将一个Connection,改为多个Connection
public static void Main(){string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=""E:\DB\NORTHWND.mdf"";Integrated Security=True;Connect Timeout=30;User Instance=True";string connectionStringNoPooling = connectionString + " ;Pooling='false' ";//SqlConnection conn = new SqlConnection(connectionString);
//new Thread(() => { ExecuteCommand(conn); }) { Name = "t1" }.Start();
//new Thread(() => { ExecuteCommand(conn); }) { Name = "t2" }.Start();
SqlConnection conn1 = new SqlConnection(connectionString);
SqlConnection conn2 = new SqlConnection(connectionString);
new Thread(() => { ExecuteCommand(conn1); }) { Name = "t1" }.Start();new Thread(() => { ExecuteCommand(conn2); }) { Name = "t2" }.Start();Console.ReadLine();}运行结果如下:
既然多个Connection比一个Connection要好,
为什么还是有人使用上面的那种写法来创建Connection呢?
我认为他们可能会认为创建多个Connection比较耗时,而且多个Connection会占用内存,影响性能等等。。
在这一点上可以使用测试数据来说明:
Run # | NCP | CP | OC |
1 | 4073 | 374 | 237 |
2 | 4032 | 341 | 298 |
3 | 3985 | 353 | 242 |
4 | 4085 | 348 | 269 |
5 | 3964 | 369 | 256 |
6 | 4203 | 330 | 207 |
7 | 4055 | 341 | 359 |
8 | 4071 | 357 | 286 |
9 | 3968 | 363 | 356 |
10 | 4023 | 349 | 359 |
AVG | 4046 | 353 | 287 |
Run #:1代表1000次查询,2代表2000次查询
NCP :Not Connection Pool ,未启用数据库连接池
CP :Connection Pool,启用数据库连接池
OC :One Connection,一个连接对象
从图表可以发现启用了连接池的方式并不比重用一个连接慢多少。
但是从稳定性,程序的健壮性来说,CP的方式明显的好于OC。
所以下次实现服务,或者是查询的时候完全可以使用
public SqlConnection Connection
{get
{return new SqlConnection(@"...");}}而不要
private SQLConnection conn = new SqlConnection(connectionString);