1

J'utilise le code EF6 en premier et, au début, je place la chaîne de connexion dans un fichier texte appelé 'Settings.txt'Migration avec chaîne de connexion dynamique dans Entity Framework code-first (chaîne de connexion du fichier texte)

les données contenues dans le fichier 'Settings.txt' est

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

Voici ce que j'utilise pour la classe dbContext:

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

J'utilise une fonction statique dans 'BaseDbContext' classe appelée 'GetConnectionString()'

Cette fonction permet de renvoyer la chaîne de connexion du fichier texte. Ce comportement fonctionne très bien lors de l'exécution, mais il ne fonctionne pas lors de l'ajout d'une migration.

C'est le problème: comment puis-je ajouter une migration de cette façon, en sachant que quand je mets la chaîne de connexion directement dans la fonction comme celui-ci

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

la commande Add-Migration travaille

Comment puis-je résoudre ce problème sans forcer la chaîne de connexion dans le code?

Répondre

1

Je résolu cela, le problème se produit à obtenir le chemin du fichier (fichier texte) en mode conception ou même tests unitaires

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

et par là, nous pouvons obtenir le chemin du fichier dans runtime-mode

0

Je suppose que vous utilisez la commande Add-Migration dans la console du gestionnaire de packages.

Si vous utilisez Add-Migration vous pouvez simplement ajouter manuellement la chaîne de connexion comme paramètre -ConnectionString:

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

Vous aurez probablement à ajouter le paramètre -ConnectionProviderName ainsi, sauf si vous avez un fournisseur défini dans votre app.config.

Je vous recommande d'arrêter d'utiliser ce fichier Settings.txt et de déplacer votre chaîne de connexion à votre fichier app.config, dans la section connectionStrings. C'est la manière recommandée de traiter les chaînes de connexion, beaucoup plus facile que d'utiliser un fichier personnalisé comme votre fichier Settings.txt.

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

Si vous faites cela, vous pouvez utiliser le paramètre -ConnectionStringName dans le Package Manager Console, en utilisant le nom que vous avez défini dans le app.config:

Add-Migration -ConnectionStringName "MyLocalDatabase" 

En outre, avec la chaîne de connexion dans votre app.config fichier vous pouvez ajouter un constructeur à votre contexte qui reçoit le nom de la chaîne de connexion en tant que paramètre et qui peut être utilisé lors de l'utilisation de la console du gestionnaire de packages:

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

Cela vous permettra d'exécuter vos commandes dans la console du gestionnaire de packages sans spécifier de paramètre de chaîne de connexion. Assurez-vous simplement que les bonnes chaînes de connexion sont incluses dans le fichier app.config du projet de démarrage sélectionné dans la console. Vous pouvez vous débarrasser de votre code GetConnectionString.Vous ne faites que ré-implémenter le code que vous avez prêt à l'emploi lors de l'utilisation de la section app.settingsconnectionString. C'est ainsi que le paramètre constructeurs de base DbContextNameOrConnectionString est destiné à être utilisé. Vous pouvez fournir une chaîne de connexion complète ou le nom d'une chaîne de connexion définie dans le fichier app.settings.

+0

merci pour votre formation –

+0

Vous êtes les bienvenus – Diana