То же приложение, разные базы данных: платформа Entity 6.X + MySQL + SQL Server

Вчера я выполнил миграцию (EF 5.0 = > EF 6.0) веб-приложения, которое использует инфраструктуру сущности для доступа к базам данных MySql и SQL Server (в частности DbContext к конкретным базам данных, а не к любому DbContext к любому типу базы данных).

Время компиляции было выполнено без каких-либо проблем, время выполнения столкнулось со мной с исключением:

Экземпляр DbConfiguration по умолчанию использовался платформой Entity Framework до того, как был обнаружен тип "MySqlEFConfiguration".

Атрибут [DbConfigurationType(typeof(MySqlEFConfiguration))] в контексте, как представляется, был проигнорирован во время выполнения, потому что контекст находится во внешней сборке (?), а используемый DbConfiguration глобальный для домена приложения, а не для контекста (?) ".

Я пробовал разные подходы, чтобы исправить это, затем перешел в Google и - неожиданно - не нашел рабочего решения.

Похоже, что описанная здесь ситуация хорошо сформирована http://forums.mysql.com/read.php?174,614148,614148 все еще не изменилась, или я пропустил некоторые очевидные вещи.

Любая обратная связь будет оценена по достоинству.

Заранее благодарю вас!

ПОДРОБНОЕ ОПИСАНИЕ:

Вход (упрощенный): - Веб-приложение ASP.NET

  • Уровень доступа к данным, реализованный через Entity Framework 6.1.1

  • Поставщики платформы Entity Framework:

    • System.Data.SqlClient 6.1.1

    • MySql.Data.MySqlClient 6.9.4

  • MY_SqlContext, первая концепция модели, предназначенная для базы данных MY SQL Server

  • Ms_SqlContext, первая концепция базы данных, предназначенная для базы данных MS SQL Server

В соответствии с общей документацией документации Entity Framework 6 и MySql Connector/Net (http://dev.mysql.com/doc/connector-net/en/connector-net-entityframework60.html), MY_SqlContext требует применения MySqlEFConfiguration.

Согласно обеим документам, упомянутым выше, для этого есть три варианта. Все трое были судимы и потерпели неудачу.

Вариант 1: добавление атрибута DbConfigurationTypeAttribute [DbConfigurationType(typeof(MySqlEFConfiguration))] в класс MY_SqlContext

Соответствующие сегменты Web.config:

<connectionStrings>
    <add name="MY_SqlContext"
         connectionString="server=.;User Id=root;password=...;Persist Security Info=True;database=MySqlDb;Use Compression=False;Use Old Syntax=False"
         providerName="MySql.Data.MySqlClient" />
    <add name="Ms_SqlContext"
         connectionString="metadata=res://*/Ms_SqlContext.csdl|res://*/Ms_SqlContext.ssdl|res://*/Ms_SqlContext.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=MsSqlDb;User ID=appuser;Password=...&quot;"
         providerName="System.Data.EntityClient" />
</connectionStrings>

<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
        <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices,  MySql.Data.Entity.EF6" />
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
</entityFramework>

После запуска приложений и начала работы веб-запросов:

Ms_SqlContext отлично работает, но пытается создать экземпляр MY_SqlContext, я получаю исключение:

Экземпляр DbConfiguration по умолчанию использовался платформой Entity Framework до того, как был обнаружен тип "MySqlEFConfiguration". Экземпляр "MySqlEFConfiguration" должен быть установлен при запуске приложения перед использованием любых функций Entity Framework или должен быть зарегистрирован в файле конфигурации приложения. См.... LinkId = 260883 для получения дополнительной информации. "

Вариант 2: вызов DbConfiguration.SetConfiguration(новый MySqlEFConfiguration()) при запуске приложения

Соответствующие сегменты Web.config(аналогично варианту 1, фактически):

<connectionStrings>
    <add name="MY_SqlContext"
         connectionString="server=.;User Id=root;password=...;Persist Security Info=True;database=MySqlDb;Use Compression=False;Use Old Syntax=False"
         providerName="MySql.Data.MySqlClient" />
    <add name="Ms_SqlContext"
         connectionString="metadata=res://*/Ms_SqlContext.csdl|res://*/Ms_SqlContext.ssdl|res://*/Ms_SqlContext.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=MsSqlDb;User ID=appuser;Password=...&quot;"
         providerName="System.Data.EntityClient" />
</connectionStrings>

<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
        <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices,  MySql.Data.Entity.EF6" />
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
</entityFramework>

Код, добавленный в Global.asax.cs:       private void Application_Start (отправитель объекта, EventArgs e)       {           DbConfiguration.SetConfiguration(новый MySqlEFConfiguration());           ...

После запуска приложений и начала веб-запросов при попытке создания экземпляра Ms_SqlContext я получаю исключение:

Был установлен экземпляр "MySqlEFConfiguration", но этот тип не был обнаружен в той же сборке, что и контекст "Ms_SqlContext". Либо введите тип DbConfiguration в ту же сборку, что и тип DbContext, используйте DbConfigurationTypeAttribute в типе DbContext, чтобы указать тип DbConfiguration, или задайте тип DbConfiguration в файле конфигурации. Подробнее... LinkId = 260883.

Вариант 3: установите тип DbConfiguration в файле конфигурации

Соответствующие сегменты Web.config

<connectionStrings>
    <add name="MY_SqlContext"
         connectionString="server=.;User Id=root;password=...;Persist Security Info=True;database=MySqlDb;Use Compression=False;Use Old Syntax=False"
         providerName="MySql.Data.MySqlClient" />
    <add name="Ms_SqlContext"
         connectionString="metadata=res://*/Ms_SqlContext.csdl|res://*/Ms_SqlContext.ssdl|res://*/Ms_SqlContext.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=MsSqlDb;User ID=appuser;Password=...&quot;"
         providerName="System.Data.EntityClient" />
</connectionStrings>

<entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
        <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices,  MySql.Data.Entity.EF6" />
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
</entityFramework>

После запуска приложений и начала работы веб-запросов:           ... Создается экземпляр Ms_SqlContext, но во время первого выполнения запроса я получаю исключение:

EntityException: { "Исходный провайдер отказался при открытии." }

InnerException: { "Невозможно подключиться к любому из указанных узлов MySQL." }

Итак, Ms_SqlContext получает конфигурацию MySql, которая, очевидно, неверна.

Ответ 1

Итак, окончательное решение:

  • Создайте собственный преемник DbConfiguration с блэкджеком и проститутками:

        public class MultipleDbConfiguration : DbConfiguration
        {
            #region Constructors 
    
            public MultipleDbConfiguration()
            {
                SetProviderServices(MySqlProviderInvariantName.ProviderName, new MySqlProviderServices());
            }
    
            #endregion Constructors
    
            #region Public methods 
    
            public static DbConnection GetMySqlConnection(string connectionString)
            {
                var connectionFactory = new MySqlConnectionFactory();
    
                return connectionFactory.CreateConnection(connectionString);
            }
    
            #endregion Public methods
        }   
    
  • Отметьте Ms_SqlContext с MultipleDbConfiguration (и ничего не делайте с этим типом DbContext)

        [DbConfigurationType(typeof(MultipleDbConfiguration))]
        partial class Ms_SqlContext
        {
        }
    
  • Отметьте Ms_SqlContext с MultipleDbConfiguration и просто MY_SqlContext (string nameOrConnectionString) с вызовом MultipleDbConfiguration.GetMySqlConnection(nameOrConnectionString)

        [DbConfigurationType(typeof(MultipleDbConfiguration))]
        partial class MY_SqlContext : DbContext
        {
                    public MY_SqlContext(string nameOrConnectionString) : base(MultipleDbConfiguration.GetMySqlConnection(nameOrConnectionString), true)
                    {}
        }
    
  • ЭТО ЭТО!!!

Ответ 2

FYIW - У меня была та же проблема. Единственное, что разрешило проблему, это добавить следующий код в начале выполнения моей программы.

var needsToBeInstantiated = new EFDBContextConfiguration();
EFDBContextConfiguration.SetConfiguration( needsToBeInstantiated );

Ответ 3

Вы правы, что только один DbConfiguration для AppDomain, а не один для каждого контекста. Существует более подробная информация о том, как его здесь указать - http://msdn.microsoft.com/en-us/data/jj680699#Moving. Если у вас несколько конфигураций и вы хотите быть уверенным, что правильный загружен, вам, вероятно, понадобится опция файла конфигурации статического метода DbConfiguration.SetConfiguration.

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

Конфигурация на основе кода действительно предназначена для конечных разработчиков для настройки своей конфигурации, а не для отдельных поставщиков для отправки предварительно испеченного (поскольку для AppDomain только один).

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

SetExecutionStrategy(MySqlProviderInvariantName.ProviderName, () => new MySqlExecutionStrategy());

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

Ответ 5

У меня была такая же ошибка, и в моем случае у меня был класс DbConfiguration, определенный в другой сборке. Несмотря на то, что он был в той же DLL, что и DbContext, я думаю, что он только ловит это во время выполнения из-за ленивой загрузки или отражения или чего-то еще.

Лучший способ, который я нашел, - установить его в файле web.config или app.config с помощью атрибута codeConfigurationType на entityFramework node, как описано здесь.