具有 SQL Server 连接的实体框架 6 尝试使用 MySqlClient 并崩溃

Posted

技术标签:

【中文标题】具有 SQL Server 连接的实体框架 6 尝试使用 MySqlClient 并崩溃【英文标题】:Entity Framework 6 with SQL Server connection tries to use MySqlClient and crashes 【发布时间】:2021-11-13 16:43:58 【问题描述】:

我有一个使用 EF6 的应用程序。它同时支持 SQL Server 和 mysql,并在运行时应用适当的设置(如果设置为 MySql,则使用 MySqlEFConfiguration 等)。

MySql 一切正常。

使用 SQL Server,会发生以下情况:

    连接建立成功。 调用context.Database.Initialize() 会导致对最新MigrationId 等的所有正常查询,如果db/tables 不存在,它会成功创建它们。 然后,它崩溃并出现以下异常:

指定的架构无效。 错误: (0,0):错误 0175:具有不变名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序未在机器或应用程序配置文件中注册,或者无法加载。有关详细信息,请参阅内部异常。

它说查看内部异常以了解详细信息,但内部异常为空。

我到处搜索,尝试无休止地摆弄配置文件(提供程序定义等),但每次都是一样的。

我试图在一个干净的项目中重现该问题但没有成功,它总是按预期工作。

为什么要尝试使用MySqlClient

编辑:

配置代码没什么特别的,只是一个

            if (Settings.Default.databaseType == "MySql")
            
                DbConfiguration.SetConfiguration(new MySqlEFConfiguration());
            

我已经验证在使用 SQL Server 时不会调用它。连接字符串也是在运行时设置的,我也验证了这些。将所有配置代码复制到干净的项目中以尝试重现问题,但我没有设法触发它。

相关配置部分:

  <system.data>
    <DbProviderFactories>
      <add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=".Net Framework Data Provider for SqlServer" type="System.Data.SqlClient.SqlClientFactory, System.Data" />
    </DbProviderFactories>
  </system.data>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework" />
    </providers>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
  <connectionStrings>
    <clear />
    <add name="mydbcontext" connectionString="" providerName="" />
  </connectionStrings>

编辑 2:这是调用堆栈以防万一。据我所知,由于某种原因 DefaultProviderFactoryResolver 给出了错误的答案。但为什么?使用自定义的 ProviderFactoryResolver 无效。

    EntityFramework.dll!<>c.AnonymousMethod(System.ArgumentException e = unknown, string n = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.DefaultProviderFactoryResolver.GetService(System.Type type = unknown, object key = unknown, System.Func<System.ArgumentException,string,object> handleFailedLookup = unknown)  C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.DefaultProviderFactoryResolver.GetService(System.Type type = unknown, object key = unknown)  C#  Non-user code
    EntityFramework.dll!<>c__DisplayClass4_0.AnonymousMethod(System.Tuple<System.Type,object> k = unknown)    C#  Non-user code
    mscorlib.dll!System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key = unknown, System.Func valueFactory = unknown)  C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.CachingDependencyResolver.GetService(System.Type type = unknown, object key = unknown)   C#  Non-user code
    EntityFramework.dll!<>c__DisplayClass5_0.AnonymousMethod(System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver r = unknown)    C#  Non-user code
    System.Core.dll!WhereSelectArrayIterator`2.MoveNext()   C#  Non-user code
    System.Core.dll!System.Linq.Enumerable.FirstOrDefault(System.Collections.Generic.IEnumerable source = unknown, System.Func predicate = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.ResolverChain.GetService(System.Type type = unknown, object key = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.RootDependencyResolver.GetService(System.Type type = unknown, object key = unknown)  C#  Non-user code
    EntityFramework.dll!<>c__DisplayClass5_0.AnonymousMethod(System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver r = unknown)    C#  Non-user code
    System.Core.dll!WhereSelectArrayIterator`2.MoveNext()   C#  Non-user code
    System.Core.dll!System.Linq.Enumerable.FirstOrDefault(System.Collections.Generic.IEnumerable source = unknown, System.Func predicate = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.ResolverChain.GetService(System.Type type = unknown, object key = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.CompositeResolver`2.GetService(System.Type type = unknown, object key = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Infrastructure.DependencyResolution.DbDependencyResolverExtensions.GetService(System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver resolver = unknown, object key = unknown) C#  Non-user code
    EntityFramework.dll!Loader.InitializeProviderManifest(System.Action<string,System.Data.Entity.Core.SchemaObjectModel.ErrorCode,System.Data.Entity.Core.Metadata.Edm.EdmSchemaErrorSeverity> addError = unknown)   C#  Non-user code
    EntityFramework.dll!Loader.OnProviderManifestTokenNotification(string token = unknown, System.Action<string,System.Data.Entity.Core.SchemaObjectModel.ErrorCode,System.Data.Entity.Core.Metadata.Edm.EdmSchemaErrorSeverity> addError = unknown)    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.Schema.HandleProviderManifestTokenAttribute(System.Xml.XmlReader reader = unknown)  C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.Schema.HandleAttribute(System.Xml.XmlReader reader = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.SchemaElement.ParseAttribute(System.Xml.XmlReader reader = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.SchemaElement.Parse(System.Xml.XmlReader reader = unknown)  C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.Schema.HandleTopLevelSchemaElement(System.Xml.XmlReader reader = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.Schema.InternalParse(System.Xml.XmlReader sourceReader = unknown, string sourceLocation = unknown)    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.Schema.Parse(System.Xml.XmlReader sourceReader = unknown, string sourceLocation = unknown)    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.SchemaObjectModel.SchemaManager.ParseAndValidate(System.Collections.Generic.IEnumerable<System.Xml.XmlReader> xmlReaders = unknown, System.Collections.Generic.IEnumerable<string> sourceFilePaths = unknown, System.Data.Entity.Core.SchemaObjectModel.SchemaDataModelOption dataModel = unknown, System.Data.Entity.Core.SchemaObjectModel.AttributeValueNotification providerNotification = unknown, System.Data.Entity.Core.SchemaObjectModel.AttributeValueNotification providerManifestTokenNotification = unknown, System.Data.Entity.Core.SchemaObjectModel.ProviderManifestNeeded providerManifestNeeded = unknown, out System.Collections.Generic.IList<System.Data.Entity.Core.SchemaObjectModel.Schema> schemaCollection = unknown)   C#  Non-user code
    EntityFramework.dll!Loader.LoadItems(System.Collections.Generic.IEnumerable<System.Xml.XmlReader> xmlReaders = unknown, System.Collections.Generic.IEnumerable<string> sourceFilePaths = unknown)   C#  Non-user code
    EntityFramework.dll!Loader..ctor(System.Collections.Generic.IEnumerable<System.Xml.XmlReader> xmlReaders = unknown, System.Collections.Generic.IEnumerable<string> sourceFilePaths = unknown, bool throwOnError = unknown, System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver resolver = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.Metadata.Edm.StoreItemCollection.Init(System.Collections.Generic.IEnumerable<System.Xml.XmlReader> xmlReaders = unknown, System.Collections.Generic.IEnumerable<string> filePaths = unknown, bool throwOnError = unknown, System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver resolver = unknown, out System.Data.Entity.Core.Common.DbProviderManifest providerManifest = unknown, out System.Data.Common.DbProviderFactory providerFactory = unknown, out string providerInvariantName = unknown, out string providerManifestToken = unknown, out System.Data.Entity.Core.Common.Utils.Memoizer<System.Data.Entity.Core.Metadata.Edm.EdmFunction,System.Data.Entity.Core.Metadata.Edm.EdmFunction> cachedCTypeFunction = unknown)  C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Core.Metadata.Edm.StoreItemCollection..ctor(System.Collections.Generic.IEnumerable<System.Xml.XmlReader> xmlReaders = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Utilities.XDocumentExtensions.GetStorageMappingItemCollection(System.Xml.Linq.XDocument model = unknown, out System.Data.Entity.Infrastructure.DbProviderInfo providerInfo = unknown)    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.Diff(System.Xml.Linq.XDocument sourceModel = unknown, System.Xml.Linq.XDocument targetModel = unknown, System.Lazy<System.Data.Entity.Migrations.Infrastructure.ModificationCommandTreeGenerator> modificationCommandTreeGenerator = unknown, System.Data.Entity.Migrations.Sql.MigrationSqlGenerator migrationSqlGenerator = unknown, string sourceModelVersion = unknown, string targetModelVersion = unknown)    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Migrations.DbMigrator.IsModelOutOfDate(System.Xml.Linq.XDocument model = unknown, System.Data.Entity.Migrations.DbMigration lastMigration = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Migrations.DbMigrator.ApplyMigration(System.Data.Entity.Migrations.DbMigration migration = unknown, System.Data.Entity.Migrations.DbMigration lastMigration = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Migrations.DbMigrator.Upgrade(System.Collections.Generic.IEnumerable<string> pendingMigrations = unknown, string targetMigrationId = unknown, string lastMigrationId = unknown)    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Migrations.DbMigrator.UpdateInternal(string targetMigration = unknown) C#  Non-user code
    EntityFramework.dll!<>c__DisplayClass42_0.AnonymousMethod() C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(System.Action mustSucceedToKeepDatabase = unknown)  C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Migrations.DbMigrator.Update(string targetMigration = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.MigrateDatabaseToLatestVersion`2.InitializeDatabase(TContext context = unknown)    C#  Non-user code
    EntityFramework.dll!<>c__DisplayClass66_0`1.AnonymousMethod()   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Internal.InternalContext.PerformInitializationAction(System.Action action = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() C#  Non-user code
    EntityFramework.dll!<>c.AnonymousMethod(System.Data.Entity.Internal.InternalContext c = unknown)  C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input = unknown)   C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(System.Action<System.Data.Entity.Internal.InternalContext> action = unknown) C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Internal.InternalContext.Initialize()    C#  Non-user code
    EntityFramework.dll!System.Data.Entity.Database.Initialize(bool force = unknown)  C#  Non-user code

【问题讨论】:

您能否为MySql添加配置代码? 【参考方案1】:

您需要为SqlServerMySql 进行不同的配置。下面是我个人的实现。


首先我创建一个扩展 DbContext 类的新类。有助于使事情分开和有条理

public class MySqlContext : DbContext

    public MySqlContext(DbContextOptions options)
     : base(options)
    
    

然后我创建了一个新的扩展类,它再次帮助一切保持井井有条。它也是通用的,因此我可以轻松添加多个上下文。 请注意,下面我使用UseSqlServer,但是,您需要使用Mysql 或UseMySQL。您可能需要为此安装软件包。

public static class ServiceCollectionExtentions

    /// <summary>
    /// Add SQL context
    /// </summary>
    /// <param name="services"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static IServiceCollection AddContext<TContext>(this IServiceCollection services, string connectionstring, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) where TContext : DbContext => services
        .AddDbContext<TContext>(options => options.UseSqlServer( // You can replace this with `UseMySQL` 
                connectionstring,
                
                // With this I change where the migrations are generated
                // This is just the project I use for the data access layer
                actions => actions.MigrationsAssembly("<Your Project Namespace>")
                                  .EnableRetryOnFailure()
            ), serviceLifetime);

这是一个示例用法:

public void ConfigureServices(IServiceCollection services)

    // Add the SQL db conneciton
    services.AddContext<MySqlContext>(Configuration.GetConnectionString("SqlConnection"));

【讨论】:

我在 EF6 上,所以没有 DbContextOptions。我猜等价的是 DbConfiguration。我尝试通过它设置 ProviderServices、ProviderFactory 和自定义 ProviderFactoryResolver,但没有任何效果。 @ASOF,您可能需要安装包Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore.DesignMicrosoft.EntityFrameworkCore.Tools【参考方案2】:

最后通过添加解决它:

  <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL"
 type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data" />

到 DbProviderFactories 配置部分。为什么在使用 SQL Server 时需要这样做,而在使用 MySql 时则不需要?我一点头绪都没有。

【讨论】:

我想你的意思是为什么 MySQL 而不是 MSSQL 需要它...这源于 EF 在幕后使用 DBConnectionFactory 而 MS 有一些包括 SQL Server、Oracle 和 OLEDB 通过注册它们在全局 machine.config 中的提供程序名称。如果您使用的是第 3 方数据库提供程序或想用替代方案(即 Oracle)覆盖这些,那么您需要手动指定 &lt;system.data&gt;&lt;DbProviderFactories&gt; 部分,除非包安装程序可能会自动为您执行此操作。 不,就是这样。没有它,连接到 MySql 工作得很好。我只是在使用 SQL Server 时崩溃了! 好的,这绝对是意外行为的陌生人方面。 :)

以上是关于具有 SQL Server 连接的实体框架 6 尝试使用 MySqlClient 并崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段

在 Visual Studio 中使用实体框架与 SQL Server 的连接问题

具有集成安全性的实体框架 SQL 连接问题

优化实体框架生成的 SQL Server 执行计划

在实体框架代码优先中,为啥我不能在连接字符串中使用 SQL Server Express?

实体框架6 - SQL Server和Oracle(SaveChanges)