8

モデルファーストアプローチでEF5を使用してEDMXを作成しました。つまり、空白のデザイナーから始めて、エンティティをモデル化しました。ここで、EDMXで定義されたこのモデルを使用できるようにしたいのですが、構成ファイルを変更せずにランタイムSQLServer接続文字列を提供します。

接続文字列をDbContextに渡す方法は知っていますが、問題はアセンブリ内のマッピングのメタデータを見つけることです。

たとえば、私のEDMXのapp.configにこの接続文字列があります

<add name="MesSystemEntities" connectionString="metadata=res://*/Data.DataContext.EntityFramework.MesSystem.csdl|res://*/Data.DataContext.EntityFramework.MesSystem.ssdl|res://*/Data.DataContext.EntityFramework.MesSystem.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=MyMachine;initial catalog=MesSystem;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

私が欠けている部分は"metadata=res://*/Data.DataContext.EntityFramework.MesSystem.csdl|res://*/Data.DataContext.EntityFramework.MesSystem.ssdl|res://*/Data.DataContext.EntityFramework.MesSystem.msl;"

DbContextプログラムでSQLServer接続文字列を渡して、メタデータ部分を「追加」できるようにしたい。

これは私がT4ファイルによって生成したいものです...

public partial class MesSystemEntities : DbContext
{
    public MesSystemEntities()
        : base("name=MesSystemEntities")
    {
    }

    public MesSystemEntities(string sqlServerConnectionString)
        : base(GetEfConnectionString(sqlServerConnectionString))
    {    
    }

    private string GetEfConnectionString(string sqlServerConnectionString)
    {
       // values added by T4 generation
       string format = "metadata=res://*/Data.DataContext.EntityFramework.MesSystem.csdl|res://*/Data.DataContext.EntityFramework.MesSystem.ssdl|res://*/Data.DataContext.EntityFramework.MesSystem.msl;;provider=System.Data.SqlClient;provider connection string=\"{0}\"";    
       return String.Format(format, sqlServerConnectionString);
    }
...
}

私の質問は、T4生成ファイルで必要なメタデータを取得して、EDMXファイルごとにハードコーディングせずにEntityFramework接続を作成するにはどうすればよいかということです。

また

プログラムでアセンブリからメタデータをロードする簡単な方法はありますか?

4

1 に答える 1

8

私は同じ問題を抱えていたので、接続文字列のすべてのメタデータに依存するのではなく (これは良い考えではないと思います)、標準の接続文字列からそれを作成する方法を書きました。(おそらく、DbContext の Extension メソッドにリファクタリングする必要がありますが、これでよいはずです)

internal static class ContextConnectionStringBuilder
{
  // Modified Version of http://stackoverflow.com/a/2294308/209259
  public static string GetEntityConnectionString(string ConnectionString, 
                                                 Type ContextType)
  {
    string result = string.Empty;

    string prefix = ContextType.Namespace
      .Replace(ContextType.Assembly.GetName().Name, "");

    if (prefix.Length > 0
        && prefix.StartsWith("."))
    {
      prefix = prefix.Substring(1, prefix.Length - 1);
    }

    if (prefix.Length > 1
        && !prefix.EndsWith("."))
    {
      prefix += ".";
    }


    EntityConnectionStringBuilder csBuilder = 
      new EntityConnectionStringBuilder();

    csBuilder.Provider = "System.Data.SqlClient";
    csBuilder.ProviderConnectionString = ConnectionString.ToString();
    csBuilder.Metadata = string.Format("res://{0}/{1}.csdl|"
                                        + "res://{0}/{1}.ssdl|"
                                        + "res://{0}/{1}.msl"
                                        , ContextType.Assembly.FullName
                                        , prefix + ContextType.Name);

    result =  csBuilder.ToString();

    return result;
  }
}

基本的な使用法は次のようなものです。

string connString = 
  ConfigurationMananager.ConnectionStrings["name"].ConnectionString;

string dbConnectionString = ContextConnectionStringBuilder(connString,
                                                           typeof(MyDbContext));

var dbContext = new MyDbContext(dbConnectionString);
于 2012-12-19T18:58:05.707 に答える