ADO.NET的範圍太廣,加上近年來的DataSourceControl與LINQ盛行,所以這邊我只做個簡介。
首先,最常看到糟糕的兩種現象,就是一個ASP.NET的工程師,
1.要存取DB,只會拖拉DataSourceControl,如SqlDataSource, LinqDataSource等等..
2.上面第一點也與這一點息息相關,就是沒有將邏輯與資料存取,和呈現層(也就是一般的UI)分隔開來。
為什麼使用DataSourceControl會有問題?如果會有問題,又為什麼ASP.NET要提供這樣子的server control供開發者使用呢?
首先,以目前ASP.NET Webform的設計原點來看,Page Life Cycle就是一個強耦合性的設計,另外Event model也很容易造成耦合性過高的問題。server control封裝後提供的方便,很容易開發人員會忽略server control背後的操作過程與方式。而DataSourceControl更是透過精靈的介面,讓開發人員可以幾近於無腦的一鍵到底,設好與DB存取的相關設定。
但,這意味著,在.aspx.cs裡面,負責UI層的程式就直接與資料存取層攪在一起,所有呈現UI、邏輯判斷以及DB存取,都被攪在一起。這是很嚴重的錯誤設計方式,完完全全的違背了高內聚低耦合的原則,既不容易做測試,碰到需求異動,也容易產生牽一髮而動全身的問題。
針對怎麼樣將UI與DB存取分開的部分,我們留在後續layer architecture再來探討。
而我們先針對ADO.NET來取代DataSourceControl做一下概念的介紹。
PS:DataSourceControl我唯一可以接受的是ObjectDataSource,因為它將Business logic與Data Access都透過一個ObjectDataSource做一個接口的隔離。
先補上ADO.NET的參考資料:http://msdn.microsoft.com/zh-tw/library/e80y5yhx(VS.80).aspx
ADO.NET入門的步驟,其實很簡單:
1.應該要先建立一段SqlConnection,而裡面會包含著ConnectionString。
目的:告訴ASP.NET,我再來這一段SQL是要對哪一個DB server進行操作,我的帳號密碼是什麼。
2.建立SqlCommand,需要用到剛剛的SqlConnection,以及我們需要執行的SQL statement。
目的:將要執行的SQL statement跟要連接的connection組合起來成為一段要執行的command。
3.Connection打開。
目的:真的要執行這段SQL statement了,請建立與DB之間的連線。
4.執行我們的SQL statement,可能沒有回傳值,可能有回傳值,用一個變數去接。
目的:得到執行SQL結果
5.關掉Connection。
目的:不佔用connection資源。
在ADO.NET中,還有兩個很重要的issue,
第一個是如何避免SQL injection,SQL injection(原理可參考:http://www.microsoft.com/taiwan/sql/SQL_Injection_G1.htm),
要解決SQL injection最基本的作法,就是使用parameter,各家db provider的範例可參考:http://msdn.microsoft.com/zh-tw/library/dw70f090.aspx
第二個則是交易(transaction)的概念,所謂的交易,簡單來說就是我會對DB進行多次異動,這多次異動如果是在同一筆交易中,這些異動應該同時成功(complete)或同時失敗且將資料還原為原本的狀態(rollback)。舉例來說,如同我們去提款機領錢,當我們已經選了提領五千塊,正對您的帳號資料進行扣款的動作,SQL已經執行完畢,但提款機突然壞了或停電造成交易中斷,導致您還沒領到真正的錢。這個交易就算失敗,錢不該從您的帳戶扣除,既然您沒實際拿到錢,就不應該扣除金額。
通常在ADO.NET裡面,使用到的transaction控管叫做TransactionScope,可以參考:http://msdn.microsoft.com/zh-tw/library/h5w5se33(v=VS.80).aspx
PS:如果是跨DB server的交易,也就是分散式交易,要留意MSDTC的問題。(一直是個很麻煩跟囉唆的問題,光設定防火牆就會讓人一肚子火了...)