Connexion de base de données MySQL dynamique pour Entity Framework 6

Je souhaite passer une chaîne de connexion dynamique au contexte entity framework. J'ai plus de 150 schémas qui sont identiques (un par compte) et je voudrais sélectionner la connexion en tant que telle:

ApplicationDbContext db = new ApplicationDbContext("dbName");

En théorie, ce serait assez facile, car je peux créer un connectionString et le passer comme argument pour le constructeur, par exemple:

public ApplicationDbContext(string dbName) : base(GetConnectionString(dbName))
{
}

public static string GetConnectionString(string dbName)
{
    // The connectionString passed is something like:
    // Server=localhost;Database={0};Uid=username;Pwd=password
    var connString =  ConfigurationManager
                         .ConnectionStrings["MyDatabase"]
                         .ConnectionString
                         .ToString();

    return String.Format(connString, dbName);
}

Je peux me connecter avec succès quand je passe juste le nom de la chaîne de connexion, mais pas quand je le génère dynamiquement comme ci-dessous. Je me rends compte maintenant que c'est parce que la chaîne de connexion dans le web.config contient l'attribut providerName="MySql.Data.MySqlClient".

Quand je passe la chaîne de connexion réelle dynamiquement à la connexion, il suppose qu'il doit se connecter à SQL Server plutôt Qu'à MySQL et échoue en raison de la chaîne de connexion invalide.

La question Est, Comment puis-je passer le nom du fournisseur à la chaîne de connexion si je le crée dynamiquement?

21
demandé sur Ian R. O'Brien 2013-11-29 06:58:09

1 réponses

Entity Framework 6 offre quelques changements subtils pratiques qui aident à la fois à faire fonctionner MySQL et à créer des connexions de base de données dynamiques.

Faire fonctionner MySQL avec Entity Framework 6

Tout d'abord, à la date de ma réponse à cette question, le seul pilote de connecteur.Net compatible avec EF6 est le MySQL. Net Connectior 6.8.1 (version bêta de développement) qui peut être trouvé sur le site officiel de MySQL ici.

Après l'installation, référez-vous au fichiers suivants de votre solution Visual Studio:

  • Mysql.Données.dll
  • Mysql.Données.Entité.EF6.dll

Vous devrez également copier ces fichiers quelque part où ils seront accessibles au projet pendant la construction, comme le répertoire bin.

Ensuite, vous devez ajouter des éléments à votre site Web.config (ou de l'Application.config si sur le Bureau) fichier.

Une chaîne de connexion:

<connectionStrings>
    <add name="mysqlCon"
         connectionString="Server=localhost;Database=dbName;Uid=username;Pwd=password" 
         providerName="MySql.Data.MySqlClient" />
</connectionStrings>

Ajoutez également le fournisseur, à l'intérieur des <entityFramework /> et <providers /> nœuds, éventuellement (c'est un must absolu dans la deuxième partie de ma réponse, lorsqu'il s'agit de bases de données définies dynamiquement) , vous pouvez changer le nœud <defaultConnectionFactory />:

<entityFramework>
    <defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6" />
    <providers>
        <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
    </providers>
</entityFramework>

Si vous modifiez defaultConnectionFactory de la connexion sql server par défaut, n'oubliez pas de supprimer les nœuds <parameter> qui sont imbriqués dans le nœud defaultConnectionFactory. MysqlConnectionFactory ne prend aucun paramètre pour son constructeur et échouera si les paramètres sont toujours y.

À ce stade, il est assez facile de se connecter à MySQL avec Entity, vous pouvez simplement vous référer à la connectionString ci-dessus par son nom. Notez que si vous vous connectez par nom, cela fonctionnera même si le nœud defaultConnectionFactory pointe toujours sur SQL Server (ce qu'il fait par défaut).

public class ApplicationDbContext: DbContext
{
    public ApplicationDbContext() : base("mysqlCon")
    {
    }
}

C'est juste une question de connexion normalement:

ApplicationDbContext db = ApplicationDbContext();

Connexion à un nom de base de données sélectionné dynamiquement

À ce stade, il est facile de se connecter à une base de données que nous pouvons passer comme paramètre, mais il ya quelques choses que nous devons faire.

Remarque Importante

Si vous ne l'avez pas déjà fait, vous devez modifier defaultConnectionFactory dans Web.config si vous souhaitez vous connecter à MySQL dynamiquement. Puisque nous allons passer une chaîne de connexion directement à le constructeur de contexte, il ne saura pas quel fournisseur utiliser et se tournera vers sa fabrique de connexions par défaut sauf si spécifié dans Web.config. Voir ci-dessus sur la façon de faire que.

Vous pouvez passer une chaîne de connexion manuellement au contexte comme ceci:

public ApplicationDbContext() : base("Server:localhost;...")
{
}

Mais pour le rendre un peu plus facile, nous pouvons faire un petit changement à la chaîne de connexion que nous avons faite ci-dessus lors de la configuration de mySQL. Ajoutez simplement un espace réservé comme indiqué ci-dessous:

<add name="mysqlCon" connectionString="Server=localhost;Database={0};Uid=username;Pwd=password" providerName="MySql.Data.MySqlClient" />

Maintenant, nous pouvons construire une méthode d'assistance et modifier la classe ApplicationDbContext comme indiqué ci-dessous:

public class ApplicationDbContext: DbContext
{
    public ApplicationDbContext(string dbName) : base(GetConnectionString(dbName))
    {
    }

    public static string GetConnectionString(string dbName)
    {
        // Server=localhost;Database={0};Uid=username;Pwd=password
        var connString = 
            ConfigurationManager.ConnectionStrings["mysqlCon"].ConnectionString.ToString();

        return String.Format(connString, dbName);
    }
}

Si vous utilisez des migrations de base de données, l'étape suivante est importante

Si vous utilisez des migrations, vous constaterez que ApplicationDbContext sera passé à votre méthode Seed par le framework et il échouera car il ne passera pas le paramètre que nous avons mis pour le nom de la base de données.

Ajoutez la classe suivante au bas de votre classe de contexte (ou n'importe où vraiment) pour résoudre ce problème.

public class MigrationsContextFactory : IDbContextFactory<ApplicationDbContext>
{
    public ApplicationDbContext Create()
    {
        return new ApplicationDbContext("developmentdb");
    }
}

Vos migrations de code et vos méthodes seed vont maintenant cibler le schéma developmentdb dans votre base de données MySQL.

J'espère que cela aide quelqu'un :)

53
répondu francisco.preller 2014-02-23 22:40:08