嚴重注意:下述內容可能完全錯誤,我只是亂理解一翻便於自己記憶。不能作為任何網友的參考,那便是嚴重誤人子弟了!
希望有懂的人看到後能告訴我真正的原理。謝謝!
對數據庫的操作貌似是程序員必須要掌握的知識,也是絕大部分的項目中要用到的知識。在.net框架下程序與數據庫之間的互操作稱為:ADO.NET。
也做過一些項目,對於程序與數據庫的操作,也會用。不明白的地方上網搜一下,查查資料,再把高手寫的代碼照復制下來照葫蘆畫瓢是了。這樣也滿足了一般項目的開發。但是一段時間不用後,又忘了,再去看看代碼是怎麼搞的,再照葫蘆畫瓢。至於ADO.NET中的一些細節並不是十分的清楚。這樣就有個問題,感覺是全憑記憶去寫的代碼,而對於為什麼代碼這麼寫並不知道。也就是說,看例子代碼是這樣一行一行排下來,我也這樣一行一行排,代碼究竟是什麼原理並不清楚。所以常常一段時間後又忘了。很想去理解代碼的意思,但是無論是買書看,還是上網查資料,總是看的不是很明白。可能是自己太笨的原因,看一些書籍和資料總覺得對於知識點的介紹太過於晦澀,有時努力看了半天也看不懂,就產生了排斥心理,看不下去了。所以有時不是我們不想去學習,而是努力學了卻學不會,我想這也是困擾很多人的一個問題。本人就是這樣的一個笨人,花了很多功夫可能還沒搞明白那是什麼意思。
好了,言歸正傳。現在我就用我自己的理解方式來表達ado.net了,理解的肯定是有很多錯誤的,但是便於我理解記憶。只要用到項目中沒問題就行了,理解錯誤就錯誤吧。
首先我們要清楚程序是程序,數據源是數據源。這是兩個不同的東西。程序不能像處理自己一樣去處理數據源,因為數據源相對於程序來說是外界,不屬於程序本身的范圍。所以程序要想處理數據緣可能需要個接口之類的。程序通過接口去處理數據源。(也可能不是接口,我瞎猜是接口的)
什麼是數據源?通俗的解釋就是能按一定規律存儲數據的一個東西。最最常見的是數據庫。當然還有其他的數據源比如xml,也是最近很火暴的。
現在我們以c#語言 ,sqlserver2000數據庫,vs2005工具開始探討ado.net。
對於sqlsever數據的操作要用System.Data.SqlClient名稱空間
剛才講了程序與數據庫是兩馬事,那麼就不能直接處理數據庫中的數據。那程序怎麼去處理數據庫呢?很簡單啊,“外交”。程序首先和數據庫聯系上,也就是建立一個連接。程序和數據庫建立個“外交關系”就可以和數據庫取得溝通了。程序怎麼和數據庫建立關系呢?c#中有個類叫:SqlConnection,它是專門負責和sql數據庫建立聯系用的。和哪個數據庫聯系,需要什麼信息等都是SqlConnection負責的。這些信息就組成了連接字符串。好了現在我們有了和數據庫連接的一個類了,就可以和數據庫連接上了。當然我們不僅僅是要連接上,最終目的是要對數據庫裡的數據進行操作的。對數據庫裡數據的操作無非,增、刪、改、查,四種方式。我個人認為(實際情況我也搞不清,不知道哪有資料能查到)程序不會直接操作數據庫裡的數據的,而是發送一個sql命令給數據庫,由數據庫自己完成操作。那麼當我們和數據庫連接上後,怎麼發送一條命令給數據庫呢?就通過c#裡的SqlCommand類,這個類就負責把命令封裝好,然後送到sqlsever數據庫中。數據庫接到SqlCommand通知後就得到了要執行的命令,數據庫按命令執行後再把反饋信息給SqlCommand的。反饋的消息可能是執行的行數、或者結果集。當SqlCommand得到數據庫反饋的信息後,程序也就完成了與數據庫的一次操作。
簡單看下過程:
1,首先程序通過SqlConnection與數據庫連上
2,通過SqlCommand傳遞命令給數據庫
3,數據庫執行命令後將執行的信息反饋給SqlCommand
也就是說SqlConnection是專門和數據庫連接的;SqlCommand負責發送命令給數據庫並得到執行結果的。這兩個類都屬於連接類。打個不准確比喻就像:有A,B兩個廠,A廠現在想要B廠的產品。那麼A廠先修條路到B廠,然後派個帶有產品訂單車子去B廠,車子通過修的那條路開到B廠,B廠接到車子送來的訂單後開始做產品,做好後裝到車子上。那麼A廠就得到想要的了。(A廠就是程序,B廠就是數據庫,路就是SqlConnection,車子就是SqlCommand)
那麼下面我們看看代碼中到底是怎麼寫的。
先看這段代碼
(以Northwind數據庫為例子,據說這個數據庫就是個例子,可以任意的動)
1//sql語句
2string strSql = "select top 10 city from Customers ";
3
4//創建一個連接(設備)
5SqlConnection cn = new SqlConnection();
6//指定是連到哪個數據庫以及其他連接信息
7cn.ConnectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
8
9//創建一個發送命令的東西,並指定用哪個連接以及其他信息
10SqlCommand cmd = new SqlCommand(strSql, cn);
11cmd.CommandType = CommandType.Text;
12
13//和數據庫連上
14cn.Open();
15
16//發送命令
17//cmd.ExecuteNonQuery();
18//cmd.ExecuteReader();
19//cmd.ExecuteScalar();
20//
21
上述代碼就基本上可以完成程序與數據庫的一次互操作了。首先創建一個連接對象SqlConnection,創建好不代表就連接上數據庫了,只有SqlConnection說連接,才連接上,也就是調用cn.Close()方法。同樣創建一個SqlCommand,不代表就發送給數據庫了。只有調用相應的方法才發送。如cmd.ExecuteNonQuery()等。
先看看SqlCommand的cmd.ExecuteNonQuery();方法。當創建好SqlCommand後,調用此方法cmd.ExecuteNonQuery()。就相當於一聲令下:發送!
數據庫得到了命令就開始執行了,並返回受影響的行數。調試後發現返回受影響的行數為 -1,也就是說數據庫沒有執行命令。怎麼回事?那是因為ExecuteNonQuery()方法發送的是更新、刪除、增加的命令,而用此方法發送查詢命令的時候數據庫並不執行。查詢命令有專門的方法。也就是cmd.ExecuteReader()方法。為什麼把發送查詢與發送更新、刪除、增加的命令分開,因為查詢命令執行後,我們最想關心的是查詢得到的數據。而更新、刪除、增加命令,我們往往只關心它是否執行成功了以及數據庫操作了多少條記錄。現在看看cmd.ExecuteReader()方法,這個方法返回一個SqlDataReader對象。SqlDataReader對象是干什麼的?官方的解釋是:提供一種從sqlserver數據庫讀取的只進流的方式。什麼意思????左思右想實在是不明白。查資料有說什麼向前進的,只讀的,輕量級的等等。越查越糊塗搞的一頭霧水!我們可能並不知道SqlDataReader到底什麼意思,但是我們一定知道它個很有價值的方法:Read()方法,並且也能用運SqlDataReader。Read()方法的官方解釋是這樣的:使SqlDataReader前進到下一條記錄。我想問,是不是前進到數據庫中的下一條記錄?也就是說是不是調用Read()方法一次,數據庫就向下查詢一條記錄?那就變成了由SqlDataReader來控制對數據庫發送命令了。但是上面說了負責對數據庫發送命令的是SqlCommand。那現在我們再從SqlCommand角度去理解,當SqlCommand調用ExecuteReader()方法的時候(發送了一個命令給數據庫),數據庫接到命令開始執行語句(通常為查詢語句)。執行完後把執行後的結果(數據記錄)返回給了SqlCommand,而SqlCommand創建一個SqlDataReader對象,並把數據庫返回的數據記錄封裝到了SqlDataReader對象裡。這個過程實際是SqlCommand對象發送命令給數據庫,數據庫執行命令並返回結果給SqlCommand,SqlCommand又生成了SqlDataReader,並把返回的結果給SqlDataReader。那現在返回的數據在SqlDataReader裡了(我們可以想象成有個表一樣的東西裝著數據),SqlDataReader再調用Read()方法,就是對SqlDataReader裡的數據的讀取了。Read()一次,就讀取一條記錄,再Read()一次往下讀取一條。此時數據不是在數據庫裡一條一條往下查詢,而是對SqlDataReader中的數據一條一條查詢。這樣我們Read()一次,就讀取一條記錄,然後再調用getxxxx(int i)方法就能得到剛剛讀取的這條記錄的每一列的值了。這樣我們就在程序中成功的從數據庫裡讀取到數據了。在這個過程中程序必須保持與數據庫的連接,如果連接一斷那麼SqlDataReader中的數據也就沒了。Close()方法調用後,SqlDataReader中數據也沒了。如果我們程序都得到了想要的值後SqlDataReader就沒用了,此時要調用Close()方法,關閉SqlDataReader。否則會占用很大的資源的。(為什麼當SqlDataReader得到數據後,還要保持連接,偶也不清楚,可能是,不是真正的把數據放在SqlDataReader裡,而是數據其實還存在數據庫裡,只是通過SqlDataReader可以對數據進行操作)
有必要再說下,上面說了SqlCommand是往數據庫發送命令的。而其中ExecuteNonQuery()方法發送的是更新、刪除、增加的命令。ExecuteReader()方法發送的通常是查詢命令。剛才用ExecuteNonQuery()方法發送了查詢命令,數據庫接到命令後並未執行。也就是講ExecuteNonQuery()方法發送查詢命令是無效的。那麼ExecuteReader()方法原本是用來發送查詢命令的,我們非要讓它發送更新、刪除、增加的命令它會執行嗎?我們不妨試試。
看如下代碼
1string strSql = "update Employees set country='china' where Employeeid>6";
2
3 SqlConnection cn = new SqlConnection();
4cn.ConnectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
5
6SqlCommand cmd = new SqlCommand(strSql, cn);
7cmd.CommandType = CommandType.Text;
8
9cn.Open();
10
11//發送命令
12cmd.ExecuteReader();
現在用更新語句,卻調用ExecuteReader()方法。執行後發現,還真能用。數據庫裡的數據改變了。我還測試過刪除,增加也可以。說明也可以把ExecuteReader()方法當成ExecuteNonQuery()方法用。不過還是不提倡這麼用,微軟專家竟然把他們分開了,肯定有他的道理,還是該怎麼用就怎麼用。
ExecuteReader()方法返回一個SqlDataReader,現在不是查詢了,而是更新語句。那麼SqlDataReader裡存放著什麼數據呢?試驗後發現不存放數據,最多也就把更新了幾條數據這個值賦給SqlDataReader。
下面來看看使用SqlDataReader得到數據中數據的完整代碼。
1//查詢語句
2string strSql = "select top 10 city from Customers ";
3
4//連接類,建立與數據庫連接的
5SqlConnection cn = new SqlConnection();
6cn.ConnectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
7
8//創建一個發送命令給數據庫的對象(SqlCommand,把查詢語句封裝進來)
9SqlCommand cmd = new SqlCommand(strSql, cn);
10cmd.CommandType = CommandType.Text;
11
12//SqlConnection 連上數據庫
13cn.Open();
14
15//SqlCommand 發送命令,數據庫得到命令後執行命令,把執行的結果給SqlCommand
16//SqlCommand 返回SqlDataReader對象並把數據交給SqlDataReader
17SqlDataReader dr = cmd.ExecuteReader();
18//把SqlDataReader裡數據一行一行讀出來
19while (dr.Read())
20{
21 //讀出一行,把這行數據添加到lbTest裡,lbTest是ListBox控件
22 lbTest.Items.Add(new ListItem(dr["city"].ToString()));
23
24}
25dr.Close();
26cn.Close();
還記得上面說的哪個比喻嗎?A廠想要B廠的產品,派個車子去,B廠把產品再交給車子。整個A廠與B廠的交易只有車子是與B廠親密接觸的。同樣程序與數據庫的互操作是sqlcommand與數據庫親密接觸的。然後數據庫把信息再反饋給sqlcommand,此時反饋的信息有兩種類別,一種就是返回了查詢的數據集,另一種是返回了數據庫執行的信息。例如:是否執行成功,影響了多少條記錄。當我們得到第一種反饋信息時,即查的數據集。就可以在程序中得到數據庫裡的數據了,但是用SqlDataReader去裝載這些數據,要求必須保持和數據庫的連接,並且是只讀的。我們能不能把數據從數據庫裡得到後,再把數據保存到程序裡,然後斷開與數據庫的連接呢?這樣我們在與數據庫斷開的情況下,依然可以處理一些數據了。c#中提供了SqlDataAdapter,DataSet可以滿足這些要求。且聽下回分解。
嚴重注意:上述內容可能完全錯誤,我只是亂理解一翻便於自己記憶。不能作為任何網友的參考。那便是嚴重誤人子弟了!
希望有高手看到後能告訴我真正的原理。謝謝!