1. ホーム
  2. c#

[解決済み] Entity Framework は実行時に接続を変更する

2023-05-25 13:51:45

質問

私のモデルとDALアセンブリを参照するWeb APIプロジェクトがあります。ユーザーにはログイン画面が表示され、そこで異なるデータベースを選択することができます。

私は以下のように接続文字列を構築します。

    public void Connect(Database database)
    {
        //Build an SQL connection string
        SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
        {
            DataSource = database.Server,
            InitialCatalog = database.Catalog,
            UserID = database.Username,
            Password = database.Password,
        };

        //Build an entity framework connection string
        EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
        {
            Provider = database.Provider,
            Metadata = Settings.Default.Metadata,
            ProviderConnectionString = sqlString.ToString()
        };
    }

まず、実際にデータコンテキストの接続を変更するにはどうすればよいのでしょうか。

次に、これはWeb APIプロジェクトなので、接続文字列(上記のログイン時に設定)はユーザーのインタラクションを通して持続するのでしょうか、それともデータコンテキストに毎回渡されるべきでしょうか?

どのように解決するのですか?

この回答は少し遅くなりましたが、私は、きちんとした小さな拡張メソッドでこれを行うための潜在的な方法があると思います。私たちは、設定上の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 MyDbEntities
var selectedDb = new MyDbEntities();
// so only reference the changed properties
// using the object parameters by name
selectedDb.ChangeDatabase
    (
        initialCatalog: "name-of-another-initialcatalog",
        userId: "jackthelady",
        password: "nomoresecrets",
        dataSource: @".\sqlexpress" // could be ip address 120.273.435.167 etc
    );

基本的な機能はすでに備わっていると思いますが、これで少し多様性を持たせられると思いました。