傳智的ADO.NET

ADO.NET基礎
程序要和數據庫交互要通過ADO.NET進行,通過ADO.NET就能再程序中執行SQL了。ADO.ENT中提供了對各種不同的數據庫的統一操作接口。
直接在項目中內嵌mdf文件的方式使用SQLSERVER數據庫(基於服務的數據庫).mdf跟項目走,用起來方便,和在數據庫服務器上創建數據庫沒什麼區別,運行的時候自動附加(Attach).
雙擊mdf文件會在“服務器資源管理器”中打開,管理方式和在Management Studio沒有什麼本質不同。要拷貝mdf文件需要關閉所有指向mdf文件的連接。
正式生產運行的時候附加到SQLSERVER上、修改連接字符串即口,除此之外沒有任何的區別,在“數據庫”節點上點右鍵“附加”;在數據庫節點上==》任何==》分離就可以得到拷來拷去mdf文件。
用的時候要在控制檯、Winform項目中在Main函數最開始的位置加入備註中的代碼。ASP.NET項目不需要。

ExecuteScalar
SqlCommand的ExecuteScalar方法用於執行查詢,並返回查詢所返回的結果集中的第一行的第一列,因爲不能確定返回值的類型,所以返回值是object類型。
cmd.CommandText="select count(*) from T+Users",int i = Convert.Toint32(cmd.ExecuteScalar())
cmd.CommandText = "select getdate()";
DateTime dt = Convert.ToDateTime(cmd.ExecuteScalar())
得到自動增長字段的主鍵值,在values關鍵字前加上outputinserted.Id,其中Id爲主鍵字段名。執行結果就試插入的主鍵值,用
ExecuteScalar執行最方便。
   cmd.CommandText = "insert into T_Users(UserName,Password) output inserted.Id values('admin','888888')";
int i = Convert.ToInt32(cmd.ExecuteScalar());

執行查詢
執行有多行結果集的用ExecuteReader
SqlDataReader reader = cmd.ExecureReader();
while(reader.Read())
{
  Console.WriteLine(reader.GetString(1));
}
reader的GetString GetInt32等方法只接受整數參數,也就是序號,
用GetOrdinal方法根據列名動態得到序號
練習:控制檯登陸程序。
爲什麼用using.
Close:關閉以後還能打開。
Dispose:直接銷燬,不能再次使用。
using在出了作用域以後調用Dispose,SqlConnection FileStream等的Dispose內部都會做這樣的判斷:判斷有沒有close,如果沒有Close就先Close再Dispose.

連接SQLServer
連接字符串:程序要通過連接字符串指定要連哪臺服務器上的 哪個實例的哪個數據庫 用什麼用戶名密碼等。
項目內嵌mdf文件形式的連接字符串"Data Source=./SQLEXPRESS;AttachDBFilename=|DataDirectory|/Database1.mdf;Integrated Security=True;User Instance=True".
"./SQLEXPRESS"表示“本機上的SQLEXPRESS實例”,如果數據庫實例名不是SQLEXPRESS,則需要修改。
"Database1.mdf"爲mdf的文件名
ADO.NET中通過SqlConnetion類創建到SQLServer的連接,SqlConnection代表一個數據庫連接,ADO.NET中的連接資源都實現了IDisposable接口,可以使用using進行資源管理。執行備註中的代碼如果成功了就OK。

將連接字符串寫在代碼中的缺點:多次重複,違反了DRY(Don't Repeat yourself)原則;如果要修改連接字符串就要修改代碼。將連接字符串寫在App.Config中。
1.添加App.config文件:添加==》新建項==》常規==》應用程序配置文件。App.config是.Net的通用配置文件,在ASP.Net中也能同樣適用。
2.在App.config中添加connectionStrings段,添加一個add項,用name屬性起義個名字(比如DbConnStr),connectionString屬性指定連接字符串。
3.在“引用”節點上點右鍵“添加引用”,找System.configuration.不是所有的.Net中的類都能直接調用,類所在的Assembly要被添加到項目的引用中纔可以。
4.ConfigurationManager.ConnectionStrings["DbConnStr"].ConnectionString得到連接字符串。
5.如何在部署的程序中修改配置。

DataSet
每次讀取數據都會創建連接 執行Command得到SqlDataReader太麻煩,讓我們封裝一個方法吧!
SqlDataReader是連接相關的,SqlDataReader中的查詢結果並不是放到程序中,而是放在數據庫服務器中,SqlDataReader只是相當於放了一個指針(遊標),只能讀取當前遊標指向的行,一旦連接斷開就不能再讀取了。這樣做的好處就是無論查詢結果有多少條,對程序佔用的內存都幾乎沒有影響。
SqlDataReader對於小數據量來說帶來的只有麻煩,優點可以忽略不計。ADO.NET中提供了數據集的機制,將查詢結果填充到本地內存中,這樣連接斷開 服務器斷開都不影響數據的讀取。
DataSet dataset = new DataSet();SqlDataAdapter adapter = new SqlDataAdapter(cmd);adapter.Fill(dataset);
SqlDataAdapter是DataSet和數據庫之間溝通的橋樑。數據集DataSet包含若干表DataTable,DataTable包含若干行DataRow.foreach(DataRow row in dataset.Table[0].Rows) row["Name"].
SQLHelper
封裝一個SQLHelper類方便使用,提供ExecuteDataTable(string sql,params SqlParameter[] parameters)
ExecuteNonQuery(string sql,params SqlParameter[] parameters) ExecuteScalar(string sql,params SqlParameter[] parameters)等方法。網上有微軟提供的最全的SQLHelper類,是Enterprise Library中的一部分。
new SqlParameter("3",0)的陷阱
sqlconnection在程序中一直保持它的open可以嗎?對於數據庫賴說,連接時非常寶貴的資源,一定要用完了就close dispose.
DataSet
可以更新行row["Name"]="yzk" 刪除行datatable.Row.Remove()  新增行datatable.NewRow().這一切都是修改內存中的DataSet 沒有修改數據庫
以調用SqlDataAdapter的Update方法將對DataSet的修改提交到數據庫,Update方法有很多重載方法,可以提交整個DataSet DataTable或者若干DataRow.但是需要爲SqlDataAdapter提供DeleteCommand UpdateCommand InsertCommand它才知道如何將對DataSet的修改提交到數據庫,由於這幾個Command的要求的格式非常苛刻,因此開發人員自己寫非常困難,可以用SqlCommandBuilder自動生成這幾個Command,用法很簡單:new SqlCommandBuilder(adapter).查看生成的Command(沒有直接賦值給SqlDataAdapter,看SqlCommandBuilder的)。SqlCommandBuilder要求表必須有主鍵。
(*)通過DataRow的RowState可以獲得行的狀態(刪除 修改 新增等);調用DataSet的GetChanges()方法得到變化的結果集,降低傳遞的資源佔用。
可空數據類型
C#中值類型(int Guid bool等)是不可以爲空的,int i = null是錯誤的,因此 int  bool等這些類型不能表示數據庫的"Null".因此C#提供了“可控類型”這種語法,只要在類型後加?就構成了可控的數據類型,比如int? bool?,這樣int?i=null就可以了。解決數據庫中的int可以爲null,而C#終int不能null的問題。
判斷可控類型是否爲空,i=null或者i.HasValue;得到可控變量的值,int i 1 = (int)i.Value.
類型轉換:不可控類型賦值給可控類型無需顯示轉換(一定成功),可控類型賦值給不可控類型則需顯示轉換(不一定成功)。
弱類型DataSet
只能通過列名引用,dataset.Tables[0].Rows[0]["Age"],如果寫錯了列名編譯時不會發現錯誤,因此開發時必須要記着列名。
int age = Convert.Toint32(dataset.Row[0]["Age"]),渠道的字段的值是object類型,必須小心翼翼的精心類型轉換,不僅麻煩,而且容易出錯。
將DataSet傳遞給其他使用者,使用者很難識別出遊拿些列可以供使用
運行時才能知道所有列明,數據綁定麻煩,無法使用Winform ASP.NET的快速開發功能。
自己動手寫強類型DataSet(類型化DataSet TypedDataSet),創建繼承自DataSet的PersonDataSet類,封裝出int?Age等屬性和bool IsAgeNull等方法,向PersonDataSet中填充。
VS自動生成強類型DataSet
添加=》新建項=?數據集
將表從服務器資源管理器拖放到DataSet中。注意拖放過程是自動根據表結構生成強類型DataSet等類,沒有把數據也拖過來,程序還是連的那個數據庫,自動將數據庫連接字符串寫在了App.Config中。
代碼中使用DataSet示例:CC——RecordTableAdapter adapter = new CC_RecordTableAdapter();如何得知Adapter的類名?選中DataSet中下半部分的Adapter Name屬性就是雷鳴。需要右鍵點擊類名-》解析取得所有的數據:adapter.GetData(),例子程序:便利顯示所有數據,i<adapter.GetData().Count;adapter.GetData()[i].Age.
常見問題:類名敲不對,表名+TableAdapter,表名+DataTable,表名+Row,然後用“解析”賴填充類名,別照着我的代碼敲。
常見問題:類的內部定義的類要通過包含namespace的全名賴引用,不能省略。類的內部定義的類就能避免同一個namespace下類不能重名的問題。
更新DataSet
調用Adapter的Update方法就可以將DataSet的改變保存到數據庫。adapter.Update(datatable)
要調用Update方法更新必須設置數據庫主鍵,後面的Delete也是如此。
常見錯誤:“當傳遞具有已修改行的DataRow集合時,更新要求有效的UpdateCommand”,要爲表設置主鍵。“誰都變了,唯有主鍵不會變”,程序要通過主鍵賴定位要更新的行。忘了設主鍵怎麼辦?先到數據庫中設置主鍵,然後再DataSet的對應DataTable上點右鍵,選擇“配置”,再對話框中點擊【完成】。好習慣:所有表都要設置主鍵!!!看看爲什麼會自動幫我們GetData Update Delte.
其他問題
插入新行,調用Insert方法
增加字段怎麼辦?DataSet設計器中點【配置】,對話框中點【查看生成器】,勾選新增加的字段即口。刪除字段同樣如此。如果是高手也可以直接手動SQL語句。
要修改字段就要重新配置生成,這就是強類型DataSet的弱點,因此強類型DataSet不一定真的就是“強“,還是叫”類型化DataSet“吧
常見錯誤:報錯:數據爲空。判斷列的值爲空的方法:Is**Null
爲什麼Select方法會填充 Update方法會更新 Insert方法會插入?沒有多麼神奇,看看Adapter的SelectCommand等屬性,是那些SQL語句在起作用,如果有需要完全可以手工調整。

類型化DataSet批量處理
創建TableAdapter對象後,首先將它打開,執行command操作後再關閉。這樣至始至終就只創建了一個連接,連接是非常寶貴

的,儘量創建很少的連接,這樣能提高效率,在進行批量處理的時候非常重要。這是從TableAdapter對象執行command的方法中看出來的==》如果以

前的連接時關閉的就打開,是關閉的就關閉,哈哈,這樣就沒必要每次執行一下command就創建一個連接。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章