我有一個EF5 ASP.NET MVC 3(Razor)網站,在IIS7下運行。現在,我希望能夠根據URL的子域將連接字符串更改爲MSSQL數據庫,例如, foo.mydomain.com
應該連接到我的「Foo」數據庫,並且bar.mydomain.com
應該連接到「Bar」數據庫。如何根據MVC網站的子域更改EF連接字符串?
很明顯,DNS記錄的設置使得它們都指向同一個網站。
實現此目的的最有效方法是什麼?
我有一個EF5 ASP.NET MVC 3(Razor)網站,在IIS7下運行。現在,我希望能夠根據URL的子域將連接字符串更改爲MSSQL數據庫,例如, foo.mydomain.com
應該連接到我的「Foo」數據庫,並且bar.mydomain.com
應該連接到「Bar」數據庫。如何根據MVC網站的子域更改EF連接字符串?
很明顯,DNS記錄的設置使得它們都指向同一個網站。
實現此目的的最有效方法是什麼?
我想出了我認爲比迄今爲止所有提議的更好的解決方案。我使用的是默認EntityModelCodeGenerator
,所以也許還有其他更好的,對其他模板解決方案 - 但是這對我的作品:
MyEntities
的另一半。OnContextCreated()
,它是從類的構造函數中調用的。這出來如下:
partial void OnContextCreated()
{
// change connection string, depending on subdomain
if (HttpContext.Current == null) return;
var host = HttpContext.Current.Request.Url.Host;
var subdomain = host.Split('.')[0];
switch (subdomain)
{
case "foo":
ChangeDB("Foo");
break;
case "bar":
ChangeDB("Bar");
break;
}
}
private void ChangeDB(string dbName)
{
var ec = Connection as EntityConnection;
if (ec == null) return;
var match = Regex.Match(ec.StoreConnection.ConnectionString, @"Initial Catalog\s*=.*?;", RegexOptions.IgnoreCase);
if (!match.Success) return;
var newDbString = "initial catalog={0};".Fmt(dbName);
ec.StoreConnection.ConnectionString = ec.StoreConnection.ConnectionString.Replace(match.Value, newDbString);
}
在web.config中使用不同的連接字符串。如果可以進行條件XSL轉換,那麼也許需要研究一下,這樣,當您在特定配置上發佈web時,Release.config會將您的Web.Config更改爲您所需要的。
或者,使用|DataDirectory|
字符串替換 - http://msdn.microsoft.com/en-us/library/cc716756.aspx
更多DataDirectory目錄字符串替換此處 http://forums.asp.net/t/1835930.aspx/1?Problem+With+Database+Connection
我想,如果你想通過這本書,爲每個獨立版本的創建構建配置並將連接字符串放在相應的web..config文件中,當您發佈時,XSL轉換會將連接字符串放入生成的web.config文件中。
我最近做了類似的事情,添加了一些自定義配置,它使用主機頭來確定必須使用的connectionStringName。
EF5有一個構造函數,它可以處理這個名字
var context = new MyDbContex("name=<DBConnectionStringName>");
我沒有使用這個解決方案,因爲我不想通過我的整個數據庫來替換所有的默認構造函數。不管怎麼說,還是要謝謝你! – 2013-03-04 13:02:28
這就是爲什麼一個人應該使用存儲庫... – TGlatzer 2013-03-04 13:05:56
你是什麼意思,「使用存儲庫」?這與我現在所做的有什麼不同? – 2013-03-04 13:10:29
你爲什麼不開始傳遞自己SqlConnection
你YourDbContext
?
var partialConString = ConfigurationManager.ConnectionStrings["DBConnectionStringName"].ConnectionString;
var connection = new SqlConnection("Initial Catalog=" + Request.Url.Host + ";" + partialConString);
var context = new MyDbContext(connection, true);
您還可以更改數據庫中的DbContext:
context.Database.Connection.ChangeDatabase("newDbname");
我沒有使用這個解決方案,因爲我不想回頭查看所有的代碼,並更改構造函數以在任何地方傳遞連接字符串。不管怎麼說,還是要謝謝你! – 2013-03-04 13:00:29
這就是爲什麼IoC容器是如此之大......無論如何,你可以在你自己的DbContext構造函數中添加數據庫更改(使用'HttpContext.Current')... – jgauffin 2013-03-04 13:23:04
是的,這正是我所做的 - 看到我對這個問題的回答。 – 2013-03-04 13:24:13
這不是很容易... 你應該改變對象上下文的構造函數來動態地更改連接字符串。 使用System.Web.HttpContext.Current.Request.Url.Host
取得子域名。然後用它來計算正確的連接字符串。
您應該在設計器生成的代碼中執行此操作。當然,這不是一個好的地方..使它使用T4模板。打開你的模型並右鍵單擊空白的設計器表面,然後選擇「添加代碼生成項目」 - > Ado.net實體對象生成。這將創建一個.tt文件。打開它並查找構造函數語法。在那裏添加你的邏輯。
祝你好運!
+1提到如何讓主機脫離HttpContext,儘管我使用自己的解決方案。不管怎麼說,還是要謝謝你! – 2013-03-04 13:01:30
我只是做了一個項目
public partial class admpDBcontext : DbContext
{
public static string name
{
get
{
if (System.Web.HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority).ToString() == "http://fcoutl.vogmtl.com")
{
return "name=admpDBcontext";
}
else { return "name=admpNyDBcontext"; }
}
}
public admpDBcontext()
: base(name)
{
}
}
而且在web.config我添加的connectionString。
爲什麼不把它們作爲兩個獨立的網站使用不同的網頁配置?這樣你就可以在配置文件中設置連接字符串。這會比每次聲明上下文時連接字符串搞亂更容易和更易維護。 – 2013-03-04 11:39:42
@DoctorJones因爲那時我每次修復一個bug或添加一個功能時都必須部署到那麼多網站。 – 2013-03-04 11:47:58
@shaul傳遞使用依賴注入的連接將是解決此問題的最佳解決方案之一。使用站點名稱參數化的DbContext工廠將是另一個。如果你的代碼不允許你這樣做,那麼把它作爲一個改進和重構的機會。 – LeffeBrune 2013-03-04 13:06:58