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


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

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

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

[DbConfigurationType(typeof(MySqlEFConfiguration))] 上下文中的属性似乎在运行时被忽略,因为上下文位于外部程序集(?)和 DbConfiguration 相反,使用的是应用程序域的全局,而不是上下文的特定(?)。“

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

看起来这里形成的情况很好 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>

应用程序启动后,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>

代码,添加到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>

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

EntityException:{“底层提供程序在Open上失败。”}

InnerException:{“无法连接到任何指定的MySQL主机。”}

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


8800
2017-10-14 13:05


起源

选项3为我修好了,thx - wodzu


答案:


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

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

        [DbConfigurationType(typeof(MultipleDbConfiguration))]
        partial class Ms_SqlContext
        {
        }
    
  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)
                    {}
        }
    
  4. 这就对了!!!


6
2017-10-21 21:44



使用#3时,我遇到了很多问题 - 构造函数只使用了一个字符串。答案在 stackoverflow.com/a/26422427/38461 给出了更多一致的结果。 - BozoJoe


仅供参考 - 我遇到了同样的问题。解决问题的唯一方法是在程序执行开始时添加以下代码。

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

4
2018-03-27 20:57



我纠正了答案。 EFDBContextConfiguration 应该用你自己的 XConfiguration 继承的类 DbConfiguration。 - Saeed Neamati
如果我们想在程序中间的某个地方调用这两行怎么办? - Faisal Hafeez
它可能很简单 DbConfiguration.SetConfiguration(new YourDbConfigurationClass()); - thepirat000


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

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

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

我的建议是不要使用他们的,创建你自己的,只注册你需要/想要的服务。例如,他们的执行策略是注册的好事 - 注册是提供者特定的:

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

当您准确地确定需要注册的内容以便其提供商工作时,可能会有一些跟踪和错误。


2
2017-10-14 19:45



你好,罗恩。实际上,我并不痴迷于在Context类型上获得一个DbConfiguration。我想在一个应用程序中使用两种不同的类型(MsSql和MySql)dbcontexts。 MySql上下文需要使用MySqlEFConfiguration类型 - 通过配置或DbConfiguration.SetConfiguration或DbConfigurationType属性。如果我配置好MySql,MySql上下文工作正常,但MsSql上下文失败,因为它们相同(对它们来说是错误的)配置。我完全不明白如何使它们在同一个应用程序中工作 - Artem Ozornin
你能告诉我你看到的错误,你应该可以在同一配置中为多个提供商配置。 - Rowan Miller
你好,罗恩。谢谢您的意见。请在问题帖子中找到更详细的错误描述,详见下面的详细说明: - Artem Ozornin
根据您的详细信息更新了答案以及更多信息。 - Rowan Miller


您可以使用带有DBConnection的上下文构造函数,并提供与上下文的正确连接。

有关示例,请参阅此问题: EF6和多种配置(SQL Server和SQL Server Compact)


1
2017-10-17 09:53



是的,我看到那个帖子。问题是我们使用自定义DbContextPooler,它与另一个构造函数重载和已经准备好的连接字符串一起运行。此外,我(简单地,不花太多时间)玩这种示例 - 在创建Sql连接期间出现一些错误 - Artem Ozornin
这个答案是恕我直言,容易被忽视。确实使用了哪个DbContext构造函数对使用的DbConfiguration有很大的影响。 - BozoJoe


我有同样的错误,在我的情况下,我有一个 DbConfiguration 另一个程序集中定义的类。即使它与...相同 DbContext,我认为它只是在运行时捕获这个因为延迟加载或反射或其他东西。

我发现的最好的方法是使用。在web.config或app.config中设置它 codeConfigurationType 属性 entityFramework 如上所述的节点 这里。


1
2018-06-15 22:26