2013-11-29 69 views
21

我希望將動態連接字符串傳遞給實體框架上下文。我有超過150的架構,其是相同的(每個帳戶之一)和我想選擇連接這樣:實體框架的動態MySQL數據庫連接6

ApplicationDbContext db = new ApplicationDbContext("dbName"); 

在理論上,這將是相當容易的,因爲我可以創建一個的connectionString並將其傳遞作爲參數的構造函數,例如:

public ApplicationDbContext(string dbName) : base(GetConnectionString(dbName)) 
{ 
} 

public static string GetConnectionString(string dbName) 
{ 
    // The connectionString passed is something like: 
    // Server=localhost;Database={0};Uid=username;Pwd=password 
    var connString = ConfigurationManager 
         .ConnectionStrings["MyDatabase"] 
         .ConnectionString 
         .ToString(); 

    return String.Format(connString, dbName); 
} 

我可以成功連接時,我傳遞的連接字符串的名稱,而不是當我動態生成它下面。我現在意識到這是因爲web.config中的連接字符串中有​​屬性。

當我將實際連接字符串動態傳遞給連接時,它假定它需要連接到SQL Server而不是MySQL,並且由於連接字符串無效而失敗。

問題是,如果我動態創建它,我如何將提供者名稱傳遞給連接字符串?

回答

53

實體框架6提供了一些方便的細微變化,這有助於獲得MySQL的工作並創建動態數據庫連接。

使MySQL與實體框架6

首先工作,在我回答這個問題的日期,兼容的唯一的.Net連接器的驅動程序與EF6是MySQL淨Connectior 6.8.1(測試版開發版),可以找到at the official MySQL website here

安裝完成後,從您的Visual Studio解決方案參考下列文件:

  • Mysql.Data.dll
  • Mysql.Data.Entity.EF6.dll

您還需要將這些文件複製到構建時可以訪問項目的某處,如bin目錄。

接下來,您需要添加一些項目到您的Web.config(或App.config,如果在基於桌面的)文件。

連接字符串:

<connectionStrings> 
    <add name="mysqlCon" 
     connectionString="Server=localhost;Database=dbName;Uid=username;Pwd=password" 
     providerName="MySql.Data.MySqlClient" /> 
</connectionStrings> 

還要添加提供者,<entityFramework /><providers />節點內,任選的(這是我的回答的第二部分,具有動態定義的數據庫打交道時絕對必要的),你可以改變<defaultConnectionFactory />節點:

<entityFramework> 
    <defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6" /> 
    <providers> 
     <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" /> 
    </providers> 
</entityFramework> 

如果更改默認的SQL Server連接的defaultConnectionFactory,不要忘記刪除<parameter>嵌套在defaultConnectionFactory節點中的節點。 MysqlConnectionFactory不會爲其構造函數使用任何參數,並且如果參數仍然存在,將會失敗。

在這個階段,通過實體連接到MySQL非常容易,您可以通過名稱來引用上面的connectionString。請注意,如果通過名稱進行連接,即使defaultConnectionFactory節點仍指向SQL Server(默認情況下它會執行此操作),也可以使用該名稱。

public class ApplicationDbContext: DbContext 
{ 
    public ApplicationDbContext() : base("mysqlCon") 
    { 
    } 
} 

的,這只是一個正常連接的事:

ApplicationDbContext db = ApplicationDbContext(); 

連接到動態選擇的數據庫名稱

在這一點上它很容易連接到一個數據庫,我們可以作爲參數傳遞,但是我們需要做一些事情。

重要提示

如果你還沒有,你必須,如果你想連接到MySQL 動態更改Web.config中的defaultConnectionFactory。由於我們將直接將連接字符串傳遞給 上下文構造函數,因此它將不知道使用哪個提供程序,並且 將轉到其默認連接工廠,除非在 web.config中指定。請參閱上文有關如何做到這一點。

您可以手動傳遞一個連接字符串的背景是這樣的:

public ApplicationDbContext() : base("Server:localhost;...") 
{ 
} 

但要使它稍微容易一些,我們可以做一個小的變化,以我們上面所做的連接字符串設定時up mySQL。只需添加一個佔位符,如下圖所示:

<add name="mysqlCon" connectionString="Server=localhost;Database={0};Uid=username;Pwd=password" providerName="MySql.Data.MySqlClient" /> 

現在我們可以建立一個輔助方法,改變ApplicationDbContext類,如下圖所示:

public class ApplicationDbContext: DbContext 
{ 
    public ApplicationDbContext(string dbName) : base(GetConnectionString(dbName)) 
    { 
    } 

    public static string GetConnectionString(string dbName) 
    { 
     // Server=localhost;Database={0};Uid=username;Pwd=password 
     var connString = 
      ConfigurationManager.ConnectionStrings["mysqlCon"].ConnectionString.ToString(); 

     return String.Format(connString, dbName); 
    } 
} 

如果您正在使用的數據庫遷移,接下來的步驟是非常重要的

如果您正在使用遷移,您將發現ApplicationDbContext將被框架傳遞給您的Seed方法,並且它將失敗,因爲它不會傳入我們爲數據庫名稱放入的參數。

將以下類添加到上下文類的底部(或真正的任何地方)以解決該問題。

public class MigrationsContextFactory : IDbContextFactory<ApplicationDbContext> 
{ 
    public ApplicationDbContext Create() 
    { 
     return new ApplicationDbContext("developmentdb"); 
    } 
} 

您的代碼優先遷移和種子方法現在將針對您的MySQL數據庫中的developmentdb模式。

希望這可以幫助別人:)

+0

你命名你的連接字符串「mysqlCon」,但在代碼中你逝去的「MyDatabase的」作爲參數。這是一個錯誤嗎? – Davor

+0

@Davor這是一個錯字,感謝您指出!現在修復。 –

+0

沒問題,你的回答也幫了我很多忙。 – Davor