[b]以前曾见过有人这样写代码:
[/b]
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(); }
}
[b]如果有人问你哪种方式比较好,你会怎么回答?
[/b]
首先验证下在多线程环境下使用一个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);
}
代码很简单,[b]模拟两个线程同时执行ExecuteCommand.方法[/b]。结果如下:
[img]http://files.jb51.net/file_images/article/201305/20130513163710135.png[/img]
[b]
可以知道在多线程环境下使用一个Connection来执行Sql语句是不安全的,[/b]
修改Main函数如下:[b]将一个Connection,改为多个Connection
[/b]
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();
}
运行结果如下:
[img]http://files.jb51.net/file_images/article/201305/20130513163710136.png[/img]
既然多个Connection比一个Connection要好,
[b]
为什么还是有人使用上面的那种写法来创建Connection呢?[/b]
我认为他们可能会认为创建多个Connection比较耗时,而且多个Connection会占用内存,影响性能等等。。
在这一点上可以使用测试数据来说明:
测试数据来自:[b]Connection-Pooling vs. Reusing one connection[/b]
|
[b]Run #[/b]
|
[b]NCP[/b]
|
[b]CP[/b]
|
[b]OC[/b]
|
|
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
|
|
[b]AVG[/b]
|
[b]4046[/b]
|
[b]353[/b]
|
[b]287[/b]
|
Run #:1代表1000次查询,2代表2000次查询
NCP :Not Connection Pool ,未启用数据库连接池
CP :Connection Pool,启用数据库连接池
OC :One Connection,一个连接对象
从图表可以发现启用了连接池的方式并不比重用一个连接慢多少。
但是从稳定性,程序的健壮性来说,CP的方式明显的好于OC。
[b]所以下次实现服务,或者是查询的时候完全可以使用
[/b]
public SqlConnection Connection
{
get
{
return new SqlConnection(@"...");
}
}
而不要
[b]private SqlConnection conn = new SqlConnection(connectionString);
[/b]