web-dev-qa-db-ja.com

接続を変更せずに、Entity Frameworkで実行時にデータベースを変更する

同じスキーマの50個のデータベースをホストするサーバーがあり、次のバージョンでEntity Frameworkの使用を開始したいと考えています。

これらのデータベースごとに新しい接続は必要ありません。 1つの接続の権限で50のデータベースすべてと通信できます。データ管理と速度のために(これはWebAPIアプリケーションです)、各データベースと通信するたびに新しいEFコンテキストをインスタンス化したくありません。もちろん、リクエストがサーバーに来るたびにこれが発生する場合を除いて、その必要はありません。

私が本当に必要なのは、USE [データベース名]コマンドを変更する機能だけです。これは、最終的にEFからサーバーに送信されると想定しています。

コードでこれを達成する方法はありますか? EFは、SaveChanges()などを呼び出す前にオンザフライで変更される可能性のあるデータベース名を参照する、読み取り/書き込みプロパティをコンテキストに保持していますか?

ありがとうございました!!!

ボブ

19
user2197022

あなたは見てみることができます:

  • SO質問 既存のSQL接続をEntityFrameworkコンテキストに渡すことについて
  • および この記事 で、既存の接続でデータベースを変更する方法について説明しています。

さらにサポートが必要な場合はお知らせください。

編集済み
2番目のリンクが 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);
}
2
alex.b

一生懸命働かないで、賢く働け!!!!

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");

データベースの構造は同じでなければなりません;)

13
Zeyad Qunees

とてもシンプルです

持っていた

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
Sakhu

これがデータベース名を変更するための私の解決策です。 Webまたはapp.configファイルから文字列をプルし、変更して、インスタンス化するだけです。

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

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);
    }

このコードを使用すると、「スキーマ」文字列でデータベース名を渡すいくつかのスキーマの同じ形式(同じテーブル名と同じフィールド)でテーブルを読み取ることができます。

0
Gian Maria

これを現在のプロジェクトに実装しました。プロジェクトには、共通のセキュリティデータベースとクライアントごとに異なるデータベースがあります。したがって、セキュリティデータベースには、他のすべてのデータベースの接続文字列を含むテーブルがあります。クライアントIDを渡して、クライアントデータベースの接続文字列を取得するだけです。

これには、2つのEDMXを追加して、1つを共通データベース用、もう1つを共通スキーマデータベース用にします。ユーザーがログインするとき、またはデータベースを選択するためのシナリオは何か、共通データベースに移動して接続文字列を取得し、必要なデータベースのオブジェクトを作成します。質問がある場合は、ここにコードサンプルがあります。

他のすべてのデータベースが共有する共通データベースのテーブルに、他のすべてのデータベースに関する接続文字列を保持できます。

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();
        }
0
Anirudh Agarwal