Passer la chaîne de connexion à DbContext code-first

90

Comment puis-je transmettre une chaîne de connexion au DbContext code-first du framework d'entité? Ma génération de base de données fonctionne correctement lorsque DbContext et la chaîne de connexion dans web.config se trouvent dans le même projet et sont nommés de la même manière. Mais maintenant, je dois déplacer le DbContext vers un autre projet, donc je teste en lui passant une chaîne de connexion comme suit:

Modèle et contexte

public class Dinner
{
    public int DinnerId { get; set; }
    public string Title { get; set; }
}

public class NerdDinners : DbContext
{
    public NerdDinners(string connString)
        : base(connString)
    {
    }
    public DbSet<Dinner> Dinners { get; set; }
}

action

    public ActionResult Index()
    {
        var db = new NerdDinners(ConfigurationManager.ConnectionStrings["NerdDinnerDb"].ConnectionString);

        var dinners = (from d in db.Dinners
                      select d).ToList();
        return View(dinners);
    }

Web.Config

<connectionStrings>
  <add name="NerdDinnerDb" connectionString="Data Source=|DataDirectory|NerdDinners.sdf" providerName="System.Data.SqlServerCe.4.0"/>    
</connectionStrings>

Si je place un point d'arrêt dans l'action et analyse le db, la chaîne de connexion est là, mais elle ne crée ni ne trouve la base de données ou quoi que ce soit.

Une erreur liée au réseau ou spécifique à une instance s'est produite lors de l'établissement d'une connexion à SQL Server. Le serveur est introuvable ou inaccessible. Vérifiez que le nom de l'instance est correct et que SQL Server est configuré pour autoriser les connexions à distance. (fournisseur: fournisseur de canaux nommés, erreur: 40 - Impossible d'ouvrir une connexion à SQL Server)

Shawn Mclean
la source
Êtes-vous absolument sûr de vous connecter au bon serveur? L'erreur est une exception SQL Server / Express typique. Cela ne ressemble pas à une connexion à une base de données Sql CE ... et EF Code créera d'abord la base de données si elle n'existe pas ... à moins que le chemin ne puisse être trouvé peut-être ...
Steven K.
Donc, fondamentalement, l'erreur d'OP a été d'envoyer toute la chaîne de connexion au constructeur DbContaxt, au lieu du seul nom. Comme le dit la documentation: "DbContext (String) Construit une nouvelle instance de contexte en utilisant la chaîne donnée comme nom ou chaîne de connexion pour la base de données"
Göran Roseen

Réponses:

85

Un peu tard dans le jeu ici, mais une autre option est:

public class NerdDinners : DbContext
{
    public NerdDinners(string connString)
    {
        this.Database.Connection.ConnectionString = connString;
    }
    public DbSet<Dinner> Dinners { get; set; }
}
Bitfiddler
la source
2
Salut! C'était la seule solution qui m'a amené quelque part. Mon problème est que j'aimerais prendre les paramètres de mon fichier de configuration Azure au lieu de web.config. Néanmoins, cette méthode ne fonctionne pas car le paramètre «Fournisseur» est manquant (il est défini comme attribut dans le fichier web.config). Des idées?
utilisateur
1
Excellente réponse! La seule modification apportée a été de supprimer le paramètre connString, puis d'utiliser la chaîne de connexion enregistrée dans les paramètres de l'application .... this.Database.Connection.ConnectionString = Properties.Settings.Default.ConnectionString
utileBee
Comment puis-je transmettre à la fois l'objet connString et DbCompiledModel en même temps que le paramètre?
Behzad Ebrahimi
Agréable. Juste "ceci" est redondant, vous pouvez le supprimer.
tocqueville
1
si votre module de classe inclut Manual changes to this file will be overwritten if the code is regenerated.dans l'en-tête, alors on peut vouloir l'implémenter dans une classe partielle selon les classes et méthodes partielles (Guide de programmation C #)
woodvi
58

Après avoir lu la documentation, je dois plutôt passer le nom de la chaîne de connexion:

var db = new NerdDinners("NerdDinnerDb");
Shawn Mclean
la source
Je l'ai mis dans mon constructeur et en ai fait une constante publique au cas où cela serait nécessaire pour référence ailleurs.
Tony Wall
37

Je pensais que j'ajouterais ce bit pour les personnes qui recherchent "Comment passer une chaîne de connexion à un DbContext": vous pouvez construire une chaîne de connexion pour votre magasin de données sous-jacent et passer la chaîne de connexion entière au constructeur de votre type dérivé de DbContext .

(Réutilisation du code de @Lol Coder) Modèle et contexte

public class Dinner
{
    public int DinnerId { get; set; }
    public string Title { get; set; }
}

public class NerdDinners : DbContext
{
    public NerdDinners(string connString)
        : base(connString)
    {
    }
    public DbSet<Dinner> Dinners { get; set; }
}

Ensuite, disons que vous construisez une chaîne de connexion SQL en utilisant le SqlConnectioStringBuilder comme ceci:

SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(GetConnectionString());

Où la méthode GetConnectionString construit la chaîne de connexion appropriée et SqlConnectionStringBuilder garantit que la chaîne de connexion est syntaxiquement correcte; vous pouvez ensuite instancier votre conetxt db comme ceci:

var myContext = new NerdDinners(builder.ToString());
Sudhanshu Mishra
la source
4
Pour vraiment coder en dur la chaîne de connexion que j'ai faite:public TestAppContext() : base("Data Source=server.company.com;Initial Catalog=SomeDB;Integrated Security=True") { }
Elijah W.Gagne
28

Dans votre DbContext, créez un constructeur par défaut pour votre DbContext et héritez de la base comme ceci:

    public myDbContext()
        : base("MyConnectionString")  // connectionstring name define in your web.config
    {
    }
Kinh Pham
la source
1
Dans mon cas, cela crée un DB nommé MyConnectionString... (oui la chaîne de connexion existe). Je dois mettre name=MyConnectionString.
Matthieu Charbonnier
2

Si vous construisez la chaîne de connexion dans l'application, vous utiliserez votre commande connString. Si vous utilisez une chaîne de connexion dans le fichier de configuration Web. Ensuite, vous utilisez le "nom" de cette chaîne.

MKunstman
la source
2

J'ai un petit exemple de solution pour ce problème.

MyDBContext.cs

 public MyDBContext(DBConnectionType ConnectionType) //: base("ConnMain")
  {
      if(ConnectionType==DBConnectionType.MainConnection)
       {
         this.Database.Connection.ConnectionString = ConfigurationManager.ConnectionStrings["ConnMain"].ConnectionString;
       }
      else if(ConnectionType==DBConnectionType.BackupConnection)
       {
         this.Database.Connection.ConnectionString = ConfigurationManager.ConnectionStrings["ConnBackup"].ConnectionString;
       }
  }

MyClass.cs

public enum DBConnectionType
 {
    MainConnection=0,
    BackupConnection=1
 }

frmMyForm.cs

 MyDBContext db = new MyDBContext(DBConnectionType.MainConnection);
                               //or
//MyDBContext db = new MyDBContext(DBConnectionType.BackupConnection);
Durgesh Pandey
la source
1

Vérifiez la syntaxe de votre chaîne de connexion dans le fichier web.config. Cela devrait être quelque chose commeConnectionString="Data Source=C:\DataDictionary\NerdDinner.sdf"

kmerkle
la source
La chaîne de connexion fonctionne lorsqu'ils utilisent tous les deux le même nom dans le même projet.
Shawn Mclean le
Cela ne fonctionne pas lorsque je veux le transmettre manuellement au DbConext
Shawn Mclean
La chaîne de connexion est correcte, le chemin n'a pas besoin d'être absolu.
Steven K.
1

Lors de l'utilisation d'un modèle EF, j'ai une chaîne de connexion dans chaque projet qui consomme le modèle EF. Par exemple, j'ai un modèle EF EDMX dans une bibliothèque de classes distincte. J'ai une chaîne de connexion dans mon projet web (mvc) afin qu'il puisse accéder à la base de données EF.

J'ai également un autre projet de test unitaire pour tester les référentiels. Pour que les référentiels puissent accéder à la base de données EF, le fichier app.config du projet de test a la même chaîne de connexion.

Les connexions DB doivent être configurées, non codées, IMO.

Danludwig
la source
2
Je dois passer manuellement la chaîne de connexion par code. J'utilise l'injection de dépendances.
Shawn Mclean le
0

Je ne vois rien de mal avec votre code, j'utilise SqlExpress et cela fonctionne bien lorsque j'utilise une chaîne de connexion dans le constructeur.

Vous avez créé un dossier App_Data dans votre projet, n'est-ce pas?

Lee Smith
la source
0

Pour tous ceux qui sont venus ici pour essayer de savoir comment définir la chaîne de connexion de manière dynamique, et qui ont eu des problèmes avec les solutions ci-dessus (comme "Le format de la chaîne d'initialisation n'est pas conforme aux spécifications commençant à l'index 0.") lors de la configuration de la chaîne de connexion dans le constructeur. Voici comment y remédier:

public static string ConnectionString
{
    get {
        if (ConfigurationManager.AppSettings["DevelopmentEnvironment"] == "true")
            return ConfigurationManager.ConnectionStrings["LocalDb"].ConnectionString;
        else
            return ConfigurationManager.ConnectionStrings["ExternalDb"].ConnectionString;
    }
}

public ApplicationDbContext() : base(ConnectionString)
{
}
Thiago Araujo
la source
0

d' ici

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
      optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["BloggingDatabase"].ConnectionString);
    }

notez que vous devrez peut-être ajouter Microsoft.EntityFrameworkCore.SqlServer

Abdullah Tahan
la source