1

私はEF6コードファーストを使用しています。最初に、接続文字列を 'Settings.txt'エンティティフレームワークの動的接続文字列を使用した移行コードファースト(テキストファイルからの接続文字列)

'SETTINGS.TXT' ファイル内のデータは、私がdbContextクラスのために使用するもの。ここ

DataProvider: sqlserver 
DataConnectionString: Data Source=.\SQLEXPRESS;Initial Catalog=MyDb;Integrated Security=True;Persist Security Info=False;Enlist=False; 

です:

public class DbDataContext : BaseDbContext 
{ 
    static DbDataContext() 
    { 
     Database.SetInitializer(new ContextInitializer()); 
    } 

    public DbDataContext():base() { } 

    public DbDataContext(string nameOrConnectionString) 
     : base(nameOrConnectionString) { } 

    ...  
} 

[DbConfigurationType(typeof(MyDbConfiguration))] 
public abstract partial class BaseDbContext : DbContext, IDbContext 
{ 
    public BaseDbContext() : this(GetConnectionString()) 
    { } 

    public BaseDbContext(string nameOrConnectionString) : base(nameOrConnectionString) 
    { } 

    public static string GetConnectionString() 
    { 
     if (DataSettings.DataSettings.Current.IsValid()) 
     { 
      return DataSettings.DataSettings.Current.DataConnectionString; 
     } 

     throw Error.Application("A connection string could not be resolved for the parameterless constructor of the derived DbContext. Either the database is not installed, or the file 'Settings.txt' does not exist or contains invalid content."); 
    } 
} 

public class MyDbConfiguration : DbConfiguration 
{ 
    public MyDbConfiguration() 
    { 
     IEfDataProvider provider = null; 

     try 
     { 
      provider = (new EfDataProviderFactory(DataSettings.DataSettings.Current).LoadDataProvider()) as IEfDataProvider; 
     } 
     catch { 
     } 

     if (provider != null) 
     { 
      base.SetDefaultConnectionFactory(provider.GetConnectionFactory()); 
     } 
    } 
} 

public partial class EfDataProviderFactory : DataProviderFactory 
{ 
    public EfDataProviderFactory() 
     : this(DataSettings.DataSettings.Current){ } 

    public EfDataProviderFactory(DataSettings.DataSettings settings) 
     : base(settings) { } 

    public override IDataProvider LoadDataProvider() 
    { 
     var providerName = Settings.DataProvider; 

     if (providerName.IsEmpty()) 
     { 
      throw new Exception("Data Settings doesn't contain a providerName"); 
     } 

     switch (providerName.ToLowerInvariant()) 
     { 
      case "sqlserver": 
       return new SqlServerDataProvider(); 

      case "sqlserverce": 
       return new SqlServerCeDataProvider(); 

      default: 
       throw new Exception(string.Format("Unsupported dataprovider name: {0}", providerName)); 
     } 
    } 
} 

public class SqlServerDataProvider : IEfDataProvider 
{ 
    public virtual IDbConnectionFactory GetConnectionFactory() 
    { 
     return new SqlConnectionFactory(); 
    } 

    public bool StoredProceduresSupported 
    { 
     get { return false; } 
    } 

    public DbParameter GetParameter() 
    { 
     return new SqlParameter(); 
    } 

    public string ProviderInvariantName 
    { 
     get { return "System.Data.SqlClient"; } 
    } 
} 

私は 'BaseDbContext' で静的関数を使用しますクラス 'GetConnectionString()'

この関数は、テキストファイルから接続文字列を返すためのものです。この動作は実行時に非常にうまく動作しますが、移行を追加するときは機能しません。

これが問題である:どのように私はこの

public static string GetConnectionString() 
    { 
     return (@"Data Source=.\\SQLEXPRESS;Initial Catalog=MyDb;Integrated Security=True;Persist Security Info=False;Enlist=False;"); 
    } 

のような機能に直接、接続文字列を入れたときにAdd-Migrationコマンドは

どのように働いていることを知って、この方法で移行を追加することができますコード内の接続文字列を強制することなくこの問題を解決できますか?

答えて

1

私はこの問題は、デザインモード、あるいは ユニットテスト

string filePath = Path.Combine(MapPath("~/App_Data/"), "Settings.txt"); 

public static string MapPath(string path) 
    { 
      path = path.Replace("~/", "").TrimStart('/').Replace('/', '\\'); 

      var testPath = Path.Combine(baseDirectory, path); 

      var dir = FindSolutionRoot(baseDirectory); 

      if (dir != null) 
       { 
        baseDirectory = Path.Combine(dir.FullName, "MyProjectName.WebAPI"); 
        testPath = Path.Combine(baseDirectory, path); 


      return testPath; 
     } 
    } 

private static DirectoryInfo FindSolutionRoot(string currentDir) 
    { 
     var dir = Directory.GetParent(currentDir); 
     while (true) 
     { 
      if (dir == null || IsSolutionRoot(dir)) 
       break; 

      dir = dir.Parent; 
     } 

     return dir; 
    } 

    private static bool IsSolutionRoot(DirectoryInfo dir) 
    { 
     return File.Exists(Path.Combine(dir.FullName, "MySolutionName.sln")); 
    } 

にファイルパス(テキストファイル)を得ることで発生 、これを解決しました

これで、ファイルパスをランタイムモード

0

パッケージマネージャコンソールでAdd-Migrationコマンドを使用していると思います。

あなたは手動であなただけの-ConnectionStringパラメータとして接続文字列を追加することができますAdd-Migrationを実行している場合:

Add-Migration -ConnectionString "Data Source=.\\SQLEXPRESS;Initial Catalog=MyDb;Integrated Security=True;Persist Security Info=False;Enlist=False;" 

あなたはおそらく、あなたのapp.configで定義されているプロバイダを持っていない限り、同様のパラメータ-ConnectionProviderNameを追加する必要があります。

このSettings.txtファイルの使用をやめ、connectionStringsセクションのapp.configファイルに接続文字列を移動することをおすすめします。これは、接続文字列を処理するための推奨方法です。Settings.txtファイルのようなカスタムファイルを使用するよりも簡単です。

<connectionStrings> 
    <add name="MyLocalDatabase" connectionString="Data Source=.\\SQLEXPRESS;Initial Catalog=MyDb;Integrated Security=True;Persist Security Info=False;Enlist=False;" /> 
</connectionStrings> 

あなたはあなたがapp.configをで定義された名前使用して、パッケージマネージャコンソールでパラメータ-ConnectionStringNameを使用できることを行う場合:あなたのapp.configに接続文字列で、また

Add-Migration -ConnectionStringName "MyLocalDatabase" 

をコンストラクタをコンテキストに追加して、接続文字列名をパラメータとして受け取り、パッケージマネージャコンソールを使用するときに使用できるコンテナを追加できます。

public DbDataContext():base("MyLocalDatabase") { } 

これにより、接続文字列パラメータをまったく指定しなくても、パッケージマネージャコンソールでコマンドを実行できます。正しい接続文字列が、コンソールで選択された開始プロジェクトのapp.configファイルに含まれていることを確認してください。

あなたはGetConnectionStringコードを取り除くことができます。app.settingsconnectionStringセクションを使用してすぐに使用できるコードを再実装するだけです。つまり、DbContextの基本コンストラクタパラメータNameOrConnectionStringが使用されます。フル接続文字列またはapp.settingsファイルで定義されている接続文字列の名前を指定できます。

+0

あなたの訓練に感謝 –

+0

あなたは歓迎です – Diana

関連する問題