2013-11-26 47 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