資料庫存取切換的思考

如果我們希望我們的程式不跟資料庫技術有太大的耦合性,我們會對於資料存取的部分進行切割,使資料存取的部分容易更換

如果我們希望我們的程式不跟資料庫技術有太大的耦合性,我們會對於資料存取的部分進行切割,使資料存取的部分容易更換,我看過的一種做法是,把資料存取的基本元件加以封裝,然後在UI及Business Logic上使用資料存取界面去存取資料,在.NET上的實作就是,把Command、Connection等ADO.NET的元件封裝起來,成為一個資料存取的方法提供者提供資料存取的物件。

這樣做,一來可以切換資料庫時,把這個資料存取的方法提供者換掉就可以達到換掉資料庫存取物件的目的。另一方面,只要一個物件即可應付多變的資料存取策略。

不過,我所看到的問題,都是在於資料庫存取的語言(SQL)散落在UI、Business Logic之後,切換資料庫所帶來的問題。畢竟每家資料庫廠商實作資料庫的方法並不同,所提供的資料庫存取語法也不相同,所以,還是可能得一個一個的資料存取語法去檢查才能成功切換。

另一個作法是,在資料存取語法上做限制,規定只能使用通用的語法來完成資料存取的動作,這樣一來,不管是那種資料庫,就能輕易切換。

這樣的作法,我並不喜歡,資料庫廠商所提供的非通用的語法,通常是針對其資料庫的存取最佳化的語法,而資料庫的效能,常常會有很大的影響,為了存取最佳化,常常會使用這些非通用的語法,這樣就回到了原來的問題了。

因此,我試著訂定了策略,改變封裝的範圍,我們讓UI、Business Logic不使用任何的SQL來存取資料,將這些資料存取的語法封裝成資料存取元件,並提供界面給程式存取,這樣一來我只要換一個相同界面的資料存取元件,就可以達到切換資料庫的效果。

在這之中,我遇到了一些問題,ADO.NET提供了兩種資料存取方式,一種是離線式的DataTable、DataSet,另一種是連線式的DataReader,對於Web來說,提供DataReader來存取資料是比較高效的方式,但是會產生連線資源管控的複雜度增加的問題,如果使用DataTable、DataSet的話,程式需要使用記憶體來暫存這些資料,但是Web程式的特性,使得這樣子的動作變成一種浪費。

這個問題在.NET 2.0倒是得到了解決,一來我可以利用DataReader來提供資料,又可以避免提供DataReader所造成的連線資源管控問題,只要利用Iterator的語法,在讀取每一筆資料的時候建立資料物件回傳即可。

不過這樣的解決又發生了一點問題,如果我將資料物件的結構定義放置在資料存取元件上,那我的程式就會對於資料存取元件產生依賴,這樣子就會變得不容易設計切換資料庫的方法。

如果可以讓程式來告訴存取元件我想建立的資料物件的方法,這樣就不會使得程式需要依賴存取元件了,這樣的想法,我想到了一個解,利用callback來達成,將我想建立物件的程式包成一個callback函式,當成參數傳給存取元件,讓存取元件執行這個函式來建構資料物件,並使用Iterator回傳,然後利用泛型來使存取元件可以不依賴程式。

這樣完成了我的資料庫的切換策略。