[Spring.Net]Spring DB ConnectionStrings設定的幾種方式

  • 12469
  • 0
  • 2010-01-21

[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

  1. 設定在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注入即可。
     
  2. 有了上面那種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裡面。
     
  3. 第三種,就挺麻煩了,希望在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一開始就會去把這些東西都建好。
    這樣注入的方式,可以廣泛的用在自己想用的地方。
     
  4. 還有遇到需求是希望connectionString可以被外面所設定,而程式不需要被修改,透過網頁或DB來設定相關server的帳號密碼資訊,
    這需求主要是為了提高資訊安全,讓User的資訊人員可以定時(or隨時)去改DB server的帳號密碼。

    有了第三種方式,其實聰明如各位,也知道,就是把GetConnect()裡寫死的connectionString,改成讀別台DB的資料,動態去組connectionString。

    至於別台DB的資訊怎麼辦,就請用第三種方式,再把他藏到別的地方,或是加上加解密的方式,這四種方式都可以混合著用。

    未來User site可能會有一台DB存放著他們各系統 DB的帳號密碼,而這台DB在他們的實際環境裡,就可以用很多實體方式來管理,提高安全性。

    anyway…這邊也列一下簡單的sample。

    以剛剛的例子來說,假設我們把帳號密碼放在別台server上,
    Spring的設定檔就加上這一段:
  5. <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/