Динамическое подключение базы данных MySQL для Entity Framework 6

asp.net c# entity-framework entity-framework-6 mysql

Вопрос

Я хочу передать динамическую строку соединения в контекст среды сущности. У меня есть более 150 схем, которые идентичны (по одному на одну учетную запись), и я хотел бы выбрать соединение как таковое:

ApplicationDbContext db = new ApplicationDbContext("dbName");

Теоретически это было бы довольно просто, поскольку я могу создать connectionString и передать его как аргумент для конструктора, например:

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

Я могу успешно соединиться, когда просто передаю имя строки подключения, но не тогда, когда я генерирую его динамически, как показано ниже. Теперь я понимаю, что это связано с тем, что строка соединения в web.config содержит атрибут providerName="MySql.Data.MySqlClient" .

Когда я передаю фактическую строку соединения динамически к соединению, он предполагает, что ему необходимо подключиться к SQL Server, а не к MySQL, и не удается из-за неправильной строки подключения.

Вопрос в том, как передать имя поставщика в строку соединения, если я создаю его динамически?

Принятый ответ

Entity Framework 6 предлагает некоторые удобные тонкие изменения, которые помогают как работать с MySQL, так и создавать динамические соединения с базой данных.

Получение MySQL работы с Entity Framework 6

Во-первых, на момент моего ответа на этот вопрос единственными драйверами .Net-соединителей, совместимыми с EF6, является MySQL .Net Connectior 6.8.1 (версия для разработки бета-версии), которую можно найти на официальном сайте MySQL здесь .

После установки обратитесь к следующим файлам из решения Visual Studio:

  • Mysql.Data.dll
  • Mysql.Data.Entity.EF6.dll

Вам также нужно будет скопировать эти файлы где-нибудь, где они будут доступны для проекта во время сборки, например, в каталоге bin.

Затем вам нужно добавить некоторые элементы в файл Web.config (или App.config, если на рабочем столе).

Строка подключения:

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

Также добавьте провайдера внутри <entityFramework /> и <providers /> (необязательно (это абсолютная необходимость во второй части моего ответа при работе с динамически определенными базами данных), вы можете изменить узел <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>

Если вы изменили defaultConnectionFactory из соединения SQL сервера по умолчанию, не забудьте удалить узлы <parameter> которые вложены в узел defaultConnectionFactory. MysqlConnectionFactory не принимает никаких параметров для своего конструктора и будет терпеть неудачу, если параметры все еще существуют.

На этом этапе довольно легко подключиться к MySQL с Entity, вы можете просто ссылаться на connectionString выше по имени. Обратите внимание, что при подключении по имени это будет работать, даже если узел defaultConnectionFactory прежнему указывает на SQL Server (что он делает по умолчанию).

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

Это просто вопрос подключения нормально:

ApplicationDbContext db = ApplicationDbContext();

Подключение к динамически выбранному имени базы данных

На данный момент легко подключиться к базе данных, которую мы можем передать как параметр, но есть несколько вещей, которые нам нужно сделать.

Важная заметка

Если вы еще этого не сделали, вы должны изменить значение defaultConnectionFactory в Web.config, если хотите динамически подключаться к MySQL. Поскольку мы будем передавать строку соединения непосредственно в конструктор контекста, он не будет знать, какой поставщик использовать и перейдет на завод по умолчанию, если он не указан в web.config. См. Выше, как это сделать.

Вы можете передать строку соединения вручную в контексте следующим образом:

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

Но чтобы сделать это немного проще, мы можем внести небольшое изменение в строку соединения, которую мы сделали выше, при настройке mySQL. Просто добавьте местозаполнитель, как показано ниже:

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

Теперь мы можем создать вспомогательный метод и изменить класс ApplicationDbContext, как показано ниже:

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

Если вы используете миграции баз данных, важно следующее

Если вы используете миграции, вы обнаружите, что ApplicationDbContext будет передан вашему методу Seed с помощью фреймворка, и он завершится неудачно, потому что он не будет передаваться в параметре, который мы вводим для имени базы данных.

Добавьте следующий класс в конец вашего контекстного класса (или где-нибудь действительно), чтобы решить эту проблему.

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

Первыми вашими кодовыми миграциями и методами семени будут теперь нацелены на схему developmentdb в вашей базе данных MySQL.

Надеюсь, это поможет кому-то :)



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему