modest violet

modest violet

開発者としてのあれこれや、日々の雑記など

your future hasn't written yet. no one's has.
by Emmett Lathrop "Doc" Brown

EntityFrameworkでconfigファイル内の接続文字列をプログラム内で動的に変更させる方法

データベースを利用する際、App.config または web.config に接続文字列が記載されます。でも、パスワードまでプレーンな状態で記載されるので、あまり好ましくありません。
.NET Frameworkのaspnet_regiis.exeを利用した暗号化は、開発中には向いていない方策なので、もっと手軽に出来ないものかと考えて、無理矢理ですが実現する事が出来たので備忘を兼ねてまとめました。


行いたいこと

  • 接続文字列のパスワードは暗号化したパスワードで記載しておきたい
  • プログラム側で動的にパスワードを複合し、接続文字列を生成する
  • 単体テストプロジェクトでも動作するように、Program.cs Mainには書かない

試した環境

  • Visual Studio 2015 Update1 (C#)
  • EntityFramework 6.x
  • サーバーファースト ※コードファーストでも可能かも

事前準備

EntityFrameworkを利用してサーバーファーストで任意のデータベースを準備しておく

手順

1.App.config / web.config に暗号化したパスワードを含む接続文字列を用意する

f:id:shin21sk:20160205212709p:plain

2.作成されたDbContextクラスのPartialクラス(_MyEntitiesPartial.cs)を作成する
public partial class MyEntities : DbContext
    {

     }
3.引数有りのコンストラクターを生成する

EntityFrameworkが自動生成するクラスに記載すると、データベースのモデルを更新する度に初期化される為、毎回設定しないといけなくなり、意味がありません。
f:id:shin21sk:20160205212712p:plain
EntityFrameworkが自動生成するクラスに、引数なしのコンストラクターが作成される為、敢えて引数有りのコンストラクターを作ります。
今回はisPasswordDecryptという引数を持たせて、Trueの場合のみ復号する処理を書いています。

public MyEntities(bool isPasswordDecrypt)
            : base("name=MyEntities")
{
    if (isPasswordDecrypt)
    {
         // ここにパスワードを復号する処理を書く
     Database.Connection.ConnectionString = 復号化したパスワードを含む接続文字列
    }
 }

EntityFrameworkが自動生成したPartialクラスでは無く、自作した方のクラスに記載します。

4.初期化用に基底クラスを用意する
public abstract class baseRepository
{
    // 初期化の際に引数をtrueにする
    // 指定しなければ従来通りの動き
    protected MyEntities db = new MyEntities(true);

}
5.DB処理を行う側(Model)で作成した基底クラスを継承する

まとめ

最初は自動生成されるクラスのコンストラクターに記載していたのですが、毎回設定し直すのが煩わしく、「こんな状態で良いはずが無い」と思い至って四苦八苦しました。
比較的簡単な方法で実現できたので本当にこれでいいのか一抹の不安が・・・。
ちなみに、同様のタイミングでinitial catalogも変更できるので、動的に接続するデータベースを替えたいといった要望も対応できます。