【问题标题】:Change Database during runtime in Entity Framework, without changing the Connection在实体框架中运行时更改数据库,而不更改连接
【发布时间】:2013-09-21 09:05:44
【问题描述】:

我有一个服务器托管 50 个具有相同架构的数据库,我想在我们的下一个版本中开始使用 Entity Framework。

我不需要为每个数据库建立新连接。一个连接的权限可以与所有 50 个数据库通信,并且为了数据管理和速度(这是一个 WebAPI 应用程序),我不想每次与每个数据库通信时都实例化一个新的 EF 上下文,如果我不必这样做,除非当然,如果每次请求到达服务器时都会发生这种情况,那么没什么大不了的。

我真正需要的是能够更改 USE [databasename] 命令,我假设它最终会从 EF 发送到服务器。

有没有办法在代码中实现这一点? EF 是否在 Context 中维护一个读/写属性,该属性引用可以在调用 SaveChanges() 等之前动态更改的数据库名称??

谢谢!!!

鲍勃

【问题讨论】:

    标签: c# sql-server entity-framework asp.net-web-api


    【解决方案1】:

    不要努力工作,聪明地工作!!!!

    MYContext localhostContext = new MYContext();
    MYContext LiveContext = new MYContext();
    //If your databases in different servers
    LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("localhost", "Live");
    //If your databases have different Names
    LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("DBName-Localhost", "DBName-Live");
    

    数据库的结构应该相同;)

    【讨论】:

      【解决方案2】:

      你可以看看:

      • SO question 关于将现有 SQL 连接传递给 EntityFramework 上下文
      • this article 描述如何 更改现有连接上的数据库。

      如果需要任何其他帮助,请告诉我。

      已编辑
      更新了第二个链接以指向 SqlConnection.ChangeDatabase 方法。
      所以最终代码看起来类似于以下内容:

      MetadataWorkspace workspace = new MetadataWorkspace(
        new string[] { "res://*/" }, 
        new Assembly[] { Assembly.GetExecutingAssembly() });
      
      using (SqlConnection sqlConnection = new SqlConnection(connectionString))
      using (EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection))
      using (NorthwindEntities context = new NorthwindEntities(entityConnection))
      {
        // do whatever on default database
        foreach (var product in context.Products)
        {
          Console.WriteLine(product.ProductName);
        }
      
        // switch database
        sqlConnection.ChangeDatabase("Northwind");
        Console.WriteLine("Database: {0}", connection.Database);
      }
      

      【讨论】:

      • 第二个链接失效。请问在哪里可以得到这篇文章的要点?
      • 注意ChangeDatabase要求连接在调用前已经打开,否则会抛出InvalidOperationException
      • 另外,至少对于 SQL Azure 和可能的其他系统,USE 语法(这是在幕后完成的)可以被禁用。如果是这种情况,在调用ChangeDatabase 时会抛出异常。
      • 最后一个Console.WriteLine不应该用sqlConnection.Database代替connection.Database吗?
      【解决方案3】:

      很简单

      我有

      public WMSEntities() : base("name=WMSEntities") //WMSEntities is conection string name in web.config also the name of EntityFramework
      {
      }
      

      已经在 edmx 文件夹的自动生成的 Model.Context.cs 中。

      为了在运行时连接到多个数据库,我在同一个文件 Model.Context.cs 中创建了另一个将连接字符串作为参数的构造函数,如下所示

      public WMSEntities(string connStringName)
                  : base("name=" + connStringName)
      {
      }
      

      现在,我在 Web.Config 中添加了其他连接字符串,例如

      <add name="WMSEntities31" connectionString="data source=TESTDBSERVER_NAME;initial catalog=TESTDB;userid=TestUser;password=TestUserPW/>
      
      <add name="WMSEntities" connectionString="data source=TESTDBSERVER_NAME12;initial catalog=TESTDB12;userid=TestUser12;password=TestUserPW12/>
      

      然后,当连接到数据库时,我调用下面的方法,将 connectionString 名称作为参数传递

      public static List<v_POVendor> GetPOVendorList(string connectionStringName)
      {
      
         using (WMSEntities db = new WMSEntities(connectionStringName))
         {               
             vendorList = db.v_POVendor.ToList();
         }
      }
      

      【讨论】:

        【解决方案4】:

        这是我仅更改数据库名称的解决方案。只需从 web 或 app.config 文件中提取字符串,修改它,然后实例化:

                string yourConnection = ConfigurationManager.ConnectionStrings["MyEntities"].ConnectionString.Replace("MyDatabase", yourDatabaseName);
                dcon = new MyEntities(yourConnection);
        

        【讨论】:

          【解决方案5】:

          我在我当前的项目中实现了这一点,其中我们为项目中的每个客户都有一个通用的安全数据库和不同的数据库。所以我们的安全数据库有一个表,其中包含每个其他数据库的连接字符串。我们只是传递客户端ID并获取客户端数据库的连接字符串..

          为此添加两个 EDMX,一个用于通用数据库,另一个用于通用模式数据库。当用户登录或您选择数据库的场景时,请转到公共数据库并获取连接字符串并创建所需数据库的对象。这是任何代码示例,如果有任何问题请告诉我..

          您可以在所有其他数据库共享的公共数据库中的表中保留与每个其他数据库相关的连接字符串。

          EntityInstance_ReviewEntities.GetContext(GetConnectionString(ClientId));
          
          
          private string GetConnectionString(int TenantId)
                  {
                      EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
                      ISecurityRepository objSecurity = new SecurityRepository();
                      string tenantConnectionString = objSecurity.GetClientConnectionString(TenantId);
                      entityBuilder.ProviderConnectionString = tenantConnectionString;
                      entityBuilder.Provider = "System.Data.SqlClient";
                      entityBuilder.Metadata = @"res://*/ClientEntity.YourEntity.csdl|res://*/ClientEntity.ADBClientEntity.ssdl|res://*/ClientEntity.YourEntity.msl";
                      return entityBuilder.ToString();
                  }
          

          【讨论】:

            【解决方案6】:

            EntityConnection.ChangeDatabase 方法不受支持,但 SqlConnection.ChangeDatabase 工作正常。

            所以你必须在实体框架数据库的构造函数中使用SqlConnection:

            using MvcMyDefaultDatabase.Models;
            using System.Data.Metadata.Edm;
            using System.Data.SqlClient;
            using System.Data.EntityClient;
            using System.Configuration;
            using System.Reflection;
            
                public ActionResult List(string Schema)
                {
                    SqlConnection sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
            
                    MetadataWorkspace workspace = new MetadataWorkspace(new string[] { "res://*/" }, new Assembly[] { Assembly.GetExecutingAssembly() });
            
                    EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection);
            
                    sqlConnection.Open();
            
                    sqlConnection.ChangeDatabase(Schema);
            
                    Models.MyEntities db = new MyEntities(entityConnection);
            
                    List<MyTableRecords> MyTableRecordsList = db.MyTableRecords.ToList();
            
                    return View(MyTableRecordsList);
                }
            

            使用此代码,您可以读取具有相同格式(相同表名和相同字段)的多个模式的表,并在“模式”字符串中传递数据库名称。

            【讨论】:

              【解决方案7】:

              对于 SQL Server,如果您只想更改数据库而不是连接,请尝试:

              public class XXXXDbContext : DbContext
              {
              
                  public string databaseName
                  {
                      set
                      {
                          Database.GetDbConnection().Open();
                          Database.GetDbConnection().ChangeDatabase(value);
                      }
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2013-12-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-10-08
                • 1970-01-01
                • 2014-06-16
                • 1970-01-01
                相关资源
                最近更新 更多