解析如何正確使用SqlConnection的實(shí)現(xiàn)方法
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;
}
}
在服務(wù)類中,新建一個全局的conn對象,然后使用conn對象來操作數(shù)據(jù)庫。
當(dāng)然,還有一些不同的版本,比如:
private SqlConnection conn = new SqlConnection();
private static SqlConnection sconn = new SqlConnection();
private SqlConnection Conn
{
get { return new SqlConnection(); }
}
如果有人問你哪種方式比較好,你會怎么回答?
首先驗(yàn)證下在多線程環(huán)境下使用一個Connection的方式:
創(chuàng)建控制臺程序:
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} 執(zhí)行完畢,{1}", Thread.CurrentThread.Name, DateTime.Now);
}
代碼很簡單,模擬兩個線程同時執(zhí)行ExecuteCommand.方法。結(jié)果如下:
可以知道在多線程環(huán)境下使用一個Connection來執(zhí)行Sql語句是不安全的,
修改Main函數(shù)如下:將一個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();
}
運(yùn)行結(jié)果如下:
既然多個Connection比一個Connection要好,
為什么還是有人使用上面的那種寫法來創(chuàng)建Connection呢?
我認(rèn)為他們可能會認(rèn)為創(chuàng)建多個Connection比較耗時,而且多個Connection會占用內(nèi)存,影響性能等等。。
在這一點(diǎn)上可以使用測試數(shù)據(jù)來說明:
測試數(shù)據(jù)來自:Connection-Pooling vs. Reusing one 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 ,未啟用數(shù)據(jù)庫連接池
CP :Connection Pool,啟用數(shù)據(jù)庫連接池
OC :One Connection,一個連接對象
從圖表可以發(fā)現(xiàn)啟用了連接池的方式并不比重用一個連接慢多少。
但是從穩(wěn)定性,程序的健壯性來說,CP的方式明顯的好于OC。
所以下次實(shí)現(xiàn)服務(wù),或者是查詢的時候完全可以使用
public SqlConnection Connection
{
get
{
return new SqlConnection(@"...");
}
}
而不要
private SqlConnection conn = new SqlConnection(connectionString);
相關(guān)文章
C#程序終極調(diào)試實(shí)現(xiàn)windbg的時間旅行
這篇文章主要介紹了C#程序終極調(diào)試實(shí)現(xiàn)windbg的時間旅行示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06C#使用Sleep(Int32)方法實(shí)現(xiàn)動態(tài)顯示時間
這篇文章主要為大家詳細(xì)介紹了C#如何使用Sleep(Int32)方法實(shí)現(xiàn)動態(tài)顯示時間,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以參考下2024-01-01基于Avalonia實(shí)現(xiàn)自定義彈窗的示例詳解
對于使用avalonia的時候某些功能需要到一些提示,比如異?;蛘叱晒Χ夹枰獙τ脩暨M(jìn)行提示,所以需要單獨(dú)實(shí)現(xiàn)彈窗功能,并且可以自定義內(nèi)部組件,這一期將手動實(shí)現(xiàn)一個簡單的小彈窗,并且很容易自定義,希望大家喜歡2023-02-02