2013-11-26 27 views
4

我有3個DB需要處理:A,B和C.每個人都有相同的表(例如:用戶,產品)。在運行時更改DbContext連接

我想讓用戶決定(在運行時)他想使用哪個數據庫。 因此...我使用EF5並創建了3個edbx文件,它們創建了以下類:ADBEntities,BDBEntities和CDBEntities。

我該如何讓他決定selecteddb,這樣我才能得到它的用戶?

我的意思是,

var dstuff = from user in selecteddb.users 
      where user.UserEmail == userEmail 
      select user.UserID; 

我想過使用反射/基類(DBEntities),但並沒有跑遠這些想法。

+0

我已經爲您添加了另一個選項。希望它有幫助... –

回答

10

有點遲了這個答案,但我認爲有一種可能的方式來做到這一點整潔的小擴展方法。正如slypete(好名字:-))所說,假設所有表/屬性都是相同的,你只需要一個類模型。在這種情況下,我們可以利用EF約定進行配置,再加上一些小的框架調用。

無論如何,不​​用再費周折,註釋的代碼和示例用法:

擴展方法類:

public static class ConnectionTools 
{ 
    // all params are optional 
    public static void ChangeDatabase(
     this DbContext source, 
     string initialCatalog = "", 
     string dataSource = "", 
     string userId = "", 
     string password = "", 
     bool integratedSecuity = true, 
     string configConnectionStringName = "") 
     /* this would be used if the 
     * connectionString name varied from 
     * the base EF class name */ 
    { 
     try 
     { 
      // use the const name if it's not null, otherwise 
      // using the convention of connection string = EF contextname 
      // grab the type name and we're done 
      var configNameEf = string.IsNullOrEmpty(configConnectionStringName) 
       ? source.GetType().Name 
       : configConnectionStringName; 

      // add a reference to System.Configuration 
      var entityCnxStringBuilder = new EntityConnectionStringBuilder 
       (System.Configuration.ConfigurationManager 
        .ConnectionStrings[configNameEf].ConnectionString); 

      // init the sqlbuilder with the full EF connectionstring cargo 
      var sqlCnxStringBuilder = new SqlConnectionStringBuilder 
       (entityCnxStringBuilder.ProviderConnectionString); 

      // only populate parameters with values if added 
      if (!string.IsNullOrEmpty(initialCatalog)) 
       sqlCnxStringBuilder.InitialCatalog = initialCatalog; 
      if (!string.IsNullOrEmpty(dataSource)) 
       sqlCnxStringBuilder.DataSource = dataSource; 
      if (!string.IsNullOrEmpty(userId)) 
       sqlCnxStringBuilder.UserID = userId; 
      if (!string.IsNullOrEmpty(password)) 
       sqlCnxStringBuilder.Password = password; 

      // set the integrated security status 
      sqlCnxStringBuilder.IntegratedSecurity = integratedSecuity; 

      // now flip the properties that were changed 
      source.Database.Connection.ConnectionString 
       = sqlCnxStringBuilder.ConnectionString; 
     } 
     catch (Exception ex) 
     { 
      // set log item if required 
     } 
    } 
} 

用法:

// assumes a connectionString name in .config of ADBEntities 
var selectedDb = new ADBEntities(); 
// so only reference the changed properties 
// using the object parameters by name 
selectedDb.ChangeDatabase 
    (
     initialCatalog: "name-of-bdb-initialcatalog", 
     userId: "jackthelad", 
     password: "nosecrets", 
     dataSource: @".\sqlexpress" // could be ip address 100.23.45.67 etc 
    ); 

我目前使用這對於準確的目的你在上面提到,到目前爲止,它給了我很好的幫助。希望它有助於你的實例。

0

假設數據庫是一致時傳遞適當的連接字符串/連接名稱,你只需要使用生成的類之一。你不需要全部三個(因爲它們是相同的)。所以讓我們選擇一個 - 比如ADBEntities

現在,您需要允許她在運行時選擇她的連接(連接字符串)。如果您已存儲在您的app.config/web.config中你的三個連接字符串,則可以使用ConfigurationManager在運行時加載起來:

var connections = ConfigurationManager.ConnectionStrings; 

目前的選擇和選擇其中一個莫名其妙:

foreach (ConnectionStringSettings connection in connections) 
    //display connection.Name 

ConnectionStringSettings selected_connection = connections[1]; 

其中DBContext的構造的將連接字符串,所以只是通過用戶選擇連接字符串的ADBEntities構造:

using (var selecteddb = new ADBEntities(selected_connection.ConnectionString)) 
{ 
    var dstuff = from user in selecteddb.users 
     where user.UserEmail == userEmail 
     select user.UserID; 
} 
+0

好的,這個想法對我來說很清楚(謝謝!),但有一個問題...... ADBEntities沒有一個構造函數來接收連接字符串(儘管它是從DBContext派生而來的)。 我應該向ADBEntities添加這樣的構造函數嗎?或者做別的...? – user3017270

+0

如果我添加下面的構造: 公共AdbEntities(字符串nameOrConnectionString) :基地( 「NAME = AdbEntities」) {} 我得到這個錯誤: 架構指定無效。錯誤: 「AdbModel.AccessCategoriesGroup」關係未加載,因爲類型「AdbModel.ProductCategory」不可用。 – user3017270