[Spring.Net]Spring DB ConnectionStrings設定的幾種方式
前言
Spring.Net拿來處理library還蠻好用的,
Spring Getting Start請參考:[修練營ASP.NET]使用Spring.Net輔助切層的專案架構
DI的概念請參考:[Software Architecture]IoC and DI
接下來進來我們的主題,一個系統要連資料庫,通常得要有connectionString,來告知程式如何建立db connection。
尤其面對一些不准在webconfig,甚至封裝在library.dll裡的spring config明碼存在帳號密碼資訊的需求,
網路上Spring.Net的中文相關資源真的少之又少…
所以這邊就順便整理一下幾種設定的方式,分享給大家。
Play it
- 設定在web.config裡,然後在Spring.Net的設定檔,根據web.config的區塊去建立connectionStrings
在web.config檔裡,新增一個區段:databaseSetting
<databaseSettings> <add key="db.datasource" value="Your DB"/> <add key="db.user" value="Your userName"/> <add key="db.password" value="Your passWord"/> <add key="db.database" value="Northwind"/> </databaseSettings>
接著在Spring的設定檔裡,將db:provider的connectionString設成讀取webconfig檔databaseSetting裡的資訊,例如:
<!-- MS SQL Server 設定 --> <object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core"> <property name="ConfigSections" value="databaseSettings"/> </object> <db:provider id="DbProvider" provider="SqlServer-2.0" connectionString="Server=${db.datasource};Database=${db.database};User ID=${db.user};Password=${db.password};"/> <object id="adoTemplate" type="Spring.Data.Core.AdoTemplate, Spring.Data"> <property name="DbProvider" ref="DbProvider"/> <property name="DataReaderWrapperType" value="Spring.Data.Support.NullMappingDataReader, Spring.Data"/> </object>
接著把adoTemplate的『DbProvider』ref到我們剛剛設定的db:provider。
要使用該provider的Dao,只需要把使用到的adtoTemplate注入即可。
- 有了上面那種web.config與Spring設定檔互相溝通的方式,當User靠邀我不要在我的web.config裡面看到DB的資訊,
我們只需要把Spring的設定檔,封裝在dll裡面,web.config上就可以看不到DB connection的資訊了。
舉例來說,剛剛Spring設定檔就把connectionString寫死:
<!-- MS SQL Server 設定 --> <object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core"> <property name="ConfigSections" value="databaseSettings"/> </object> <db:provider id="DbProvider" provider="SqlServer-2.0" connectionString="Server=Your_DB;Database=Northwind;User ID=Your userName;Password=Your password;"/> <object id="adoTemplate" type="Spring.Data.Core.AdoTemplate, Spring.Data"> <property name="DbProvider" ref="DbProvider"/> <property name="DataReaderWrapperType" value="Spring.Data.Support.NullMappingDataReader, Spring.Data"/> </object>
這樣部署的時候,DB connection就會被封在library.dll裡面。
- 第三種,就挺麻煩了,希望在Spring的設定檔裡面,看不到connection的資訊,
這邊就要透過Spring的DI,把DB provider相關的資訊,封裝在別的class裡面,
(無聊=.= 看的到設定檔,應該也看的到其他code,沒法子...就是有這樣需求)
先新增一個class,Core.Utility.DBProvider,裡面有一個Method叫GetDbProvider(),回傳設定好的DBprovider回來。
值得注意的是要宣告成static,Spring才能用它。
public static DbProvider GetDbProvider(string dBdriver, string serverName) { IDbProvider db = DbProviderFactory.GetDbProvider(dBdriver); db.ConnectionString = GetConnect(serverName); return (DbProvider)db; } private static string GetConnect(string serverName) { string returnValue = string.Empty; switch (serverName) { case "第一個DB": returnValue = "Server=第一個DB;Database=Northwind;User ID=91;Password=91;"; break; case "第二個DB": returnValue = "Server=第二個DB;Database=Northwind;User ID=91;Password=91;"; break; default: break; } return returnValue; }
GetDbProvider要傳兩個參數進來,第一個是連接的DB種類,第二個是我們用來判斷這次要return的DB connection是哪一台。
接著就是Spring的設定檔DI神奇的地方,(現在說神奇,弄不出來的時候整個幹幹叫的...)
<object id="第一個DB_dbProvider" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"> <property name="TargetType" value="Core.Utility.DBProvider, Core"/> <property name="TargetMethod" value="GetDbProvider"/> <property name="Arguments"> <list> <value>SqlServer-2.0</value> <value>第一個DB</value> </list> </property> </object> <object id="第一個DB_adoTemplate" type="Spring.Data.Core.AdoTemplate, Spring.Data"> <property name="DbProvider" ref="第一個DB_dbProvider"/> <property name="DataReaderWrapperType" value="Spring.Data.Support.NullMappingDataReader, Spring.Data"/> </object>
我們將原本的adoTemplate的DbProvider指到我們定義的object『第一個DB_dbProvider』,
而第一個DB_dbProvider會去使用 Core.Utility.DBProvider這支class的GetDbProvider()這個method。
並且傳入兩個參數,第一個參數為『SqlServer-2.0』,第二個參數為『第一個DB』。
就這樣,當系統第一次RUN起來,Spring一開始就會去把這些東西都建好。
這樣注入的方式,可以廣泛的用在自己想用的地方。
- 還有遇到需求是希望connectionString可以被外面所設定,而程式不需要被修改,透過網頁或DB來設定相關server的帳號密碼資訊,
這需求主要是為了提高資訊安全,讓User的資訊人員可以定時(or隨時)去改DB server的帳號密碼。
有了第三種方式,其實聰明如各位,也知道,就是把GetConnect()裡寫死的connectionString,改成讀別台DB的資料,動態去組connectionString。
至於別台DB的資訊怎麼辦,就請用第三種方式,再把他藏到別的地方,或是加上加解密的方式,這四種方式都可以混合著用。
未來User site可能會有一台DB存放著他們各系統 DB的帳號密碼,而這台DB在他們的實際環境裡,就可以用很多實體方式來管理,提高安全性。
anyway…這邊也列一下簡單的sample。
以剛剛的例子來說,假設我們把帳號密碼放在別台server上,
Spring的設定檔就加上這一段:
<db:provider id="Joey_dbProvider"
provider="SqlServer-2.0"
connectionString="Server=localhost\SQLEXPRESS;Database=Northwind;User ID=91;Password=91;"/>
<object id="Joey_adoTemplate" type="Spring.Data.Core.AdoTemplate, Spring.Data">
<property name="DbProvider" ref="Joey_dbProvider"/>
<property name="DataReaderWrapperType" value="Spring.Data.Support.NullMappingDataReader, Spring.Data"/>
</object>
<object id="GetDBinfoDao" type="Core.Dao.DataAccess.GetDBinfoDao, Core">
<property name="adoTemplate" ref="Joey_adoTemplate"/>
</object>
<object id="DBProvider" type="Core.Utility.DBProvider, Core">
<property name="getDBinfoDao" ref="GetDBinfoDao"/>
</object>
我們透過GetDBinfoDao去讀我們系統需要的帳號密碼出來,而這個Dao使用的provider是localhost\SQLEXPRESS裡的資料,
小的這邊是先使用第二種方式,簡化sample code。
接著我們看一下GetDBinfoDao裡面在幹嘛。
/// <summary>
/// 根據DB server name,來讀取存放帳號密碼的資料庫
/// </summary>
/// <param name="serverName"></param>
/// <returns></returns>
public DataTable GetDBinfomation(string serverName)
{
string sql = @" SELECT *
FROM DBinfo
WHERE serverName=@serverName";
IDbParameters objParameters = CreateDbParameters();
objParameters.Add("serverName", DbType.String).Value = serverName;
return AdoTemplate.DataTableCreateWithParams(CommandType.Text, sql, objParameters);
}
就是回傳一個DataTable回來,裡面有帳號密碼。
接著我們就把這個Dao注入到Core.Utility.DbProvider裡面,稍微改一下我們的GetConnect()。
//將帳號密碼拉到另一台db server,另一個資料表中
public static GetDBinfoDao getDBinfoDao { get; set; }
private static string GetConnect(string serverName)
{
DataTable dt = getDBinfoDao.GetDBinfomation(serverName);
string returnValue = string.Empty;
if (dt.Rows.Count == 1)
{
string userinfo = "User ID=" + dt.Rows[0]["account"].ToString() + @";Password=" + dt.Rows[0]["password"].ToString();
switch (serverName)
{
case "第一台DB":
returnValue = "Server=第一台DB;Database=Northwind;" + userinfo;
break;
case "第二台DB":
returnValue = "Server=第二台DB;Database=Northwind;" + userinfo;
break;
default:
break;
}
}
return returnValue;
}
就這樣,繞了一大圈,有沒有意義?恩…見仁見智囉,User爽就好…
結論
Spring.Net最麻煩的就是資源很多,不過怎麼查幾乎都會查到java的Spring。
概念雖然都一樣,不過實做上要查實際例子,還是相當麻煩…
所以有撞牆過的經驗,就整理給大家,希望大家可以做的順利一點。
blog 與課程更新內容,請前往新站位置:http://tdd.best/