相同的应用程序,不同的数据库:实体框架6.X + MySQL + SQL Server

Art*_*nin 11 mysql sql-server entity-framework-6

昨天我做了一个Web应用程序的迁移(EF 5.0 => EF 6.0),它使用实体框架来访问MySql和SQL Server数据库(特别DbContext是特定数据库,而不是DbContext任何类型的数据库).

编译时间没有任何问题,运行时遇到异常:

在发现"MySqlEFConfiguration"类型之前,实体框架使用了默认的DbConfiguration实例.

[DbConfigurationType(typeof(MySqlEFConfiguration))]上下文中的属性似乎在运行时被忽略,因为上下文位于外部程序集(?)中,而DbConfigurationused对应用程序域是全局的,而不是上下文(?)的特定内容.

我尝试了不同的方法来解决它,然后谷歌搜索它 - 惊喜 - 找不到有效的解决方案.

貌似情况描述在这里形成良好http://forums.mysql.com/read.php?174,614148,614148仍未改变,或者我错过了一些明显的事情.

任何反馈将不胜感激.

先感谢您!

详细说明:

输入(简化): - ASP.NET Web应用程序

  • 通过Entity Framework 6.1.1实现的数据访问层

  • 实体框架提供者:

    • 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>
Run Code Online (Sandbox Code Playgroud)

应用程序启动后,Web请求开始处理:

Ms_SqlContext工作正常,但尝试创建一个MY_SqlContext实例,我得到异常:

在发现"MySqlEFConfiguration"类型之前,实体框架使用了默认的DbConfiguration实例.必须在应用程序启动时设置"MySqlEFConfiguration"实例,然后才能使用任何Entity Framework功能,或者必须在应用程序的配置文件中注册.有关详细信息,请参阅... LinkId = 260883."

选项2:在应用程序启动时调用DbConfiguration.SetConfiguration(new 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>
Run Code Online (Sandbox Code Playgroud)

代码,添加到Global.asax.cs:private void Application_Start(object sender,EventArgs e){DbConfiguration.SetConfiguration(new MySqlEFConfiguration()); ...

在应用程序启动并且Web请求开始处理尝试创建Ms_SqlContext实例后,我得到异常:

设置了"MySqlEFConfiguration"的实例,但未在与"Ms_SqlContext"上下文相同的程序集中发现此类型.将DbConfiguration类型放在与DbContext类型相同的程序集中,在DbContext类型上使用DbConfigurationTypeAttribute指定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>
Run Code Online (Sandbox Code Playgroud)

在应用程序启动并且Web请求开始处理之后:...创建了Ms_SqlContext实例,但在第一次查询执行期间,我得到了异常:

EntityException:{"底层提供程序在Open上失败."}

InnerException:{"无法连接到任何指定的MySQL主机."}

所以,Ms_SqlContext得到的MySql配置显然是错误的.

Art*_*nin 6

所以,最终的解决方案是:

  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
        }   
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用MultipleDbConfiguration标记Ms_SqlContext(并且对这种DbContext不做任何其他操作)

        [DbConfigurationType(typeof(MultipleDbConfiguration))]
        partial class Ms_SqlContext
        {
        }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用MultipleDbConfiguration标记Ms_SqlContext,并使用调用MultipleDbConfiguration.GetMySqlConnection(nameOrConnectionString)调用MY_SqlContext(string nameOrConnectionString)

        [DbConfigurationType(typeof(MultipleDbConfiguration))]
        partial class MY_SqlContext : DbContext
        {
                    public MY_SqlContext(string nameOrConnectionString) : base(MultipleDbConfiguration.GetMySqlConnection(nameOrConnectionString), true)
                    {}
        }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 这就对了!!!


Row*_*ler 2

您是正确的,每个 AppDomain 只有一个 DbConfiguration,而不是每个上下文一个。有关如何指定它的更多信息,请参见此处 - http://msdn.microsoft.com/en-us/data/jj680699#Moving。如果您有多个配置并希望确保加载正确的配置,那么您可能需要静态 DbConfiguration.SetConfiguration 方法的配置文件选项。

看起来 MySQL 正在替换依赖解析器中的一堆服务,但它们注册的实现仅适用于 MySQL。

基于代码的配置实际上是为最终开发人员设置其配置而设计的,而不是为各个提供商提供预制的配置(因为每个 AppDomain 只有一个)。

我的建议是不要使用他们的服务,创建您自己的服务并且仅注册您需要/想要的服务。例如,注册他们的执行策略是一件好事 - 并且注册是特定于提供商的:

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

当您准确计算出需要注册哪些内容才能使其提供商正常工作时,可能会出现一些尝试和错误。