在我目前的工作中, 環境略為有點複雜, 牽涉到開發、測試和正式環境, 而使用的資料庫伺服器也有兩到三個。如果能夠動態地切換不同環境下所使用的資料庫連線字串, 一定對工作相當有幫助。
當然, 如果我都寫 ADO.NET 指令去指定連線字串, 我自然可以動態地決定應該採用哪一個連線字串。但是, 我又不想放棄簡單易用的 GridView/FormView 搭配 SqlDataSource 的作業方式。無可誨言的, 對於那些許多很小型的資料表、很少的資料、很簡單的工作, 實在沒有什麼能比上述情境更方便處理了!
對於 SqlDataSource 裡那道 ConnectionString="<%$ ConnectionStrings:ConnectionString1 %>" 指令, 絕大部份初學者都會認為就是這樣了。你除了指定寫在 Web.config 中的既有連線字串外, 你沒辦法自己任意指定它去讀取某個字串, 或者某個物件的屬性。如果你去查閱官方文件, 你也看不到任何其它相關且有用的資訊。
但是, 如果情況可以改變呢?
例如, 假設我寫了一個 SqlHelper 類別, 並且加入一個 MyConnString 屬性; 這個屬性可以視實體網站是哪一個而決定採用哪一個寫在 Web.config 裡的 ConnectionString, 那麼, 使用如下的寫法, 就可以讓 SqlDataSource 不再堅持只能讀取 Web.config 中的 ConnectionString 了:
<asp:SqlDataSource ConnectionString="<%$ SQL: Johnny.SqlHelper.MyConnString %>" ...
如上, "SQL" 是我自訂的一個前綴字串 (Prefix), 後面的 Johnny.SqlHelper.MyConnString 則是我的一個還輯物件。基本上, 你不一定要採用和我一樣的做法, 你可以使用更多、有變化的寫法; 關於這點, 我有空時可以再補充。為求簡捷, 我目前只介紹我所採用的寫法。
要達到上述功能, 我們必須先實作 ExpressionPrefix 這個 attribute, 而且要覆寫 GetCodeExpression 這個方法, 讓它回傳一個 CodeExpression 物件:
using System.Web.Compilation; using System.CodeDom; using System.Web.UI; ... [ExpressionPrefix("SQL")] public class SqlHelper : System.Web.Compilation.ExpressionBuilder { private static string testConnStringName = "MyConnectionString1"; private static string productionConnStringName = "MyConnectionString2"; public static string currentConnectionString { get { return (IsProductionServer) ? productionConnStringName : testConnStringName; } } public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context) { return new CodeSnippetExpression(entry.Expression); } public static string BoConnString { get { Configuration rootWebConfig = (HttpContext.Current != null) ? WebConfigurationManager.OpenWebConfiguration(HostingEnvironment.ApplicationVirtualPath) : ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); System.Configuration.ConnectionStringSettings connString; if (0 < rootWebConfig.ConnectionStrings.ConnectionStrings.Count) { connString = rootWebConfig.ConnectionStrings.ConnectionStrings[currentConnectionString]; return connString.ToString(); } else return null; } } public static bool IsProductionServer { get { return System.Environment.MachineName == "JOHNNY_PC"; // 自行撰寫程式決定 } } }
在上述程式中, IsProductionServer 這個屬性是用來判斷網站運行的主機是否為 Production Server。你可以簡單地把上述程式中的 "JOHNNY_PC" 已成你的正式主機的名稱即可。
上述程式的重點在於實作 ExpressionPrefix 並覆寫 GetCodeExpression 兩部份。其它幾行程式完全只是我的業務邏輯, 你不一定要寫得跟它一樣。
事實上這個方法不只可以應用於設定 SqlDataSource 的 Connection String; 它實際上可以套用到任何伺服器控制項。例如以下這個控制項
<asp:Label runat="server" Text='<%$ Util: Johnny.Utility.DeveloperName %>' />
此處的 Util 是依照上述寫法, 寫在 Johnny.Utility 這個類別的 Prefix, 而 Johnny.Utility.DeveloperName 則是這個類別的一個文字屬性。
因此, 這篇文章所介紹的程式寫法, 可以應用在許多不同的情境之下。
參考:
沒有留言:
張貼留言