在 EF6 中的 MySQL/SQL 服务器之间切换
Switching between MySQL/SQL Server in EF6
我有一个在 MySQL 和 SQL 服务器上运行的项目。在过去的几周里,我使用基于现有 SQL 服务器架构。
现在我需要用 MySQL 进行测试。即使我使用了“适当的”MySQL 配置,应用程序也会在从 MySql.Data.MySqlClient.MySqlConnection
到 System.Data.SqlClient.SqlConnection
的 ClassCastException
上崩溃
代码:
//Autowired by Spring
public auitool2014Entities DataContext{get;set;}
public IList<News> FindAllValid()
{
return (from News news in DataContext.news where news.annullata == 0 select news).ToList();
}
Spring定义:
<object id="dataContext" singleton="false" scope="request" type="DiagnosticoSite.Models.auitool2014Entities, Auitool2014" factory-object="dataContextFactory" factory-method="Build" destroy-method="Dispose" ></object>
Spring工厂:
public auitool2014Entities Build()
{
return new auitool2014Entities();
}
错误消息(翻译自本地化)
Unable to cast object of type 'MySql.Data.MySqlClient.MySqlConnection' to type 'System.Data.SqlClient.SqlConnection'.
跟踪堆栈跟踪:
[InvalidCastException: Unable to cast object of type 'MySql.Data.MySqlClient.MySqlConnection' type 'System.Data.SqlClient.SqlConnection'.]
System.Data.SqlClient.SqlCommand.set_DbConnection(DbConnection value) +26
System.Data.Common.DbCommand.set_Connection(DbConnection value) +9
System.Data.Entity.Internal.InterceptableDbCommand.set_DbConnection(DbConnection value) +41
System.Data.Common.DbCommand.set_Connection(DbConnection value) +9
System.Data.Entity.Core.Common.Utils.CommandHelper.SetStoreProviderCommandState(EntityCommand entityCommand, EntityTransaction entityTransaction, DbCommand storeProviderCommand) +123
System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.PrepareEntityCommandBeforeExecution(EntityCommand entityCommand) +314
System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +70
System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute(ObjectContext context, ObjectParameterCollection parameterValues) +1283
System.Data.Entity.Core.Objects.<>c__DisplayClass7.<GetResults>b__6() +185
System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction(Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) +448
System.Data.Entity.Core.Objects.<>c__DisplayClass7.<GetResults>b__5() +271
System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Func`1 operation) +251
System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +648
System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0() +68
System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() +68
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +381
System.Linq.Enumerable.ToList(IEnumerable`1 source) +58
DiagnosticoSite.Data.Managers.Spring.NewsManagerImpl.FindAllValid() in d:\Documents\Visual Studio 2013\Projects\Auitool\Auitool2014\Data\Managers\Spring\NewsManagerImpl.cs:16
配置如下:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
我基本上将连接字符串更改为 MySQL 连接字符串
<add name="myConnectionString" connectionString="metadata=res://*/Models.Auitool2014.csdl|res://*/Models.Auitool2014.ssdl|res://*/Models.Auitool2014.msl;provider=Mysql.Data.MysqlClient;provider connection string="Server=localhost;Database=auitemp;Uid=root;Pwd=root;Allow Zero Datetime=True;CharSet=latin1;Pooling=True;Min Pool Size=5"" providerName="System.Data.EntityClient" />
编译后如何在两个数据库之间切换?我提到 Spring 是因为我的 DbContext
是 request
范围的对象,可以通过工厂对象轻松实例化。
调查进展
我发现堆栈跟踪报告涉及以下 class:System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy
。这显然是 SQL 服务器包的一部分。我需要了解 EF 如何实例化它。在 EF 源代码中我 see
var executionStrategy = ExecutionStrategy
?? DbProviderServices.GetExecutionStrategy(QueryState.ObjectContext.Connection, QueryState.ObjectContext.MetadataWorkspace);
真的,那一定是 MySql.Data.entity.EF6.MySqlExecutionStrategy
的实例
修复了 EntityFramework 的 configuration
<entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<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>
MySql.Data.Entity.MySqlEFConfiguration
是关键。总结一下,为了从 SQL 服务器切换到 MySQL 我必须:
- 编辑该死的连接字符串
- 提供商属性始终为
System.Data.EntityClient
- 在连接 string 中,将提供商更改为
MySql.Data.MySqlClient
- 用上面的
替换entityFramework
标签
我有一个在 MySQL 和 SQL 服务器上运行的项目。在过去的几周里,我使用基于现有 SQL 服务器架构。
现在我需要用 MySQL 进行测试。即使我使用了“适当的”MySQL 配置,应用程序也会在从 MySql.Data.MySqlClient.MySqlConnection
到 System.Data.SqlClient.SqlConnection
ClassCastException
上崩溃
代码:
//Autowired by Spring
public auitool2014Entities DataContext{get;set;}
public IList<News> FindAllValid()
{
return (from News news in DataContext.news where news.annullata == 0 select news).ToList();
}
Spring定义:
<object id="dataContext" singleton="false" scope="request" type="DiagnosticoSite.Models.auitool2014Entities, Auitool2014" factory-object="dataContextFactory" factory-method="Build" destroy-method="Dispose" ></object>
Spring工厂:
public auitool2014Entities Build()
{
return new auitool2014Entities();
}
错误消息(翻译自本地化)
Unable to cast object of type 'MySql.Data.MySqlClient.MySqlConnection' to type 'System.Data.SqlClient.SqlConnection'.
跟踪堆栈跟踪:
[InvalidCastException: Unable to cast object of type 'MySql.Data.MySqlClient.MySqlConnection' type 'System.Data.SqlClient.SqlConnection'.]
System.Data.SqlClient.SqlCommand.set_DbConnection(DbConnection value) +26
System.Data.Common.DbCommand.set_Connection(DbConnection value) +9
System.Data.Entity.Internal.InterceptableDbCommand.set_DbConnection(DbConnection value) +41
System.Data.Common.DbCommand.set_Connection(DbConnection value) +9
System.Data.Entity.Core.Common.Utils.CommandHelper.SetStoreProviderCommandState(EntityCommand entityCommand, EntityTransaction entityTransaction, DbCommand storeProviderCommand) +123
System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.PrepareEntityCommandBeforeExecution(EntityCommand entityCommand) +314
System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +70
System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute(ObjectContext context, ObjectParameterCollection parameterValues) +1283
System.Data.Entity.Core.Objects.<>c__DisplayClass7.<GetResults>b__6() +185
System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction(Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) +448
System.Data.Entity.Core.Objects.<>c__DisplayClass7.<GetResults>b__5() +271
System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Func`1 operation) +251
System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +648
System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0() +68
System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() +68
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +381
System.Linq.Enumerable.ToList(IEnumerable`1 source) +58
DiagnosticoSite.Data.Managers.Spring.NewsManagerImpl.FindAllValid() in d:\Documents\Visual Studio 2013\Projects\Auitool\Auitool2014\Data\Managers\Spring\NewsManagerImpl.cs:16
配置如下:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
我基本上将连接字符串更改为 MySQL 连接字符串
<add name="myConnectionString" connectionString="metadata=res://*/Models.Auitool2014.csdl|res://*/Models.Auitool2014.ssdl|res://*/Models.Auitool2014.msl;provider=Mysql.Data.MysqlClient;provider connection string="Server=localhost;Database=auitemp;Uid=root;Pwd=root;Allow Zero Datetime=True;CharSet=latin1;Pooling=True;Min Pool Size=5"" providerName="System.Data.EntityClient" />
编译后如何在两个数据库之间切换?我提到 Spring 是因为我的 DbContext
是 request
范围的对象,可以通过工厂对象轻松实例化。
调查进展
我发现堆栈跟踪报告涉及以下 class:System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy
。这显然是 SQL 服务器包的一部分。我需要了解 EF 如何实例化它。在 EF 源代码中我 see
var executionStrategy = ExecutionStrategy
?? DbProviderServices.GetExecutionStrategy(QueryState.ObjectContext.Connection, QueryState.ObjectContext.MetadataWorkspace);
真的,那一定是 MySql.Data.entity.EF6.MySqlExecutionStrategy
修复了 EntityFramework 的 configuration
<entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<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>
MySql.Data.Entity.MySqlEFConfiguration
是关键。总结一下,为了从 SQL 服务器切换到 MySQL 我必须:
- 编辑该死的连接字符串
- 提供商属性始终为
System.Data.EntityClient
- 在连接 string 中,将提供商更改为
MySql.Data.MySqlClient
- 提供商属性始终为
- 用上面的 替换
entityFramework
标签