如果在 DB 服务器不可用时尝试第一次查询,则 Devart/EFCore 永久失败

Posted

技术标签:

【中文标题】如果在 DB 服务器不可用时尝试第一次查询,则 Devart/EFCore 永久失败【英文标题】:Devart/EFCore Permanent failure if First Query attempted while DB server is unavailable 【发布时间】:2021-07-09 23:34:23 【问题描述】:

我们有几个微服务构建在 aspnetcore 和实体框架之上,并使用 Devart 的 mysql EntityFramework 连接器。我注意到,如果我们的任何应用程序尝试的第一个查询由于数据存储不可访问而失败,那么故障似乎被缓存了,当数据库最终处于活动状态时,异常仍然返回给用户代码。

作为此问题诊断的一部分,我尝试在应用程序运行时禁用数据库,在这种情况下,一旦数据库再次可用,应用程序似乎能够恢复,因此我怀疑问题与连接有关可能在模型初始化期间被缓存。

我还尝试禁用服务提供者缓存,这也可以让应用程序恢复,但代价是每次都必须初始化服务提供者,所以这不能在我们的应用程序中使用,但会增加这个想法的分量该错误与某种形式的缓存有关。

以前有没有其他人遇到过/看到过这个问题?你的解决方案是什么?

这是上下文的堆栈跟踪:

   at   .    (String , String , String , String , Int32 , String , Int32 , SshOptions  , SslOptions  , ProxyOptions  , MySqlHttpOptions  , HttpOptions  , Int32  )
   at   .(MySqlConnection , String , String , String , String , Int32 , Int32 , MySqlProtocol  , Boolean  , Boolean  )
   at   ..ctor(   , MySqlConnection )
   at   .   (  , Object , DbConnectionBase )
   at  .(  ,   , DbConnectionBase )
   at  .(  , DbConnectionBase )
   at  .(DbConnectionBase )
   at  .(DbConnectionBase )
   at  .(DbConnectionBase )
   at  .   (DbConnectionBase )
   at Devart.Common.DbConnectionBase.Open()
   at Devart.Data.MySql.MySqlConnection.()
   at Devart.Data.MySql.MySqlConnection.Open()
   at Devart.Common.Entity.c7.a(DbConnection A_0)
   at Devart.Common.Entity.c7.b(DbConnection A_0)
   at Devart.Data.MySql.Entity.ad.a(DbConnection A_0)
   at Devart.Data.MySql.Entity.aa.b(RelationalOptionsExtension A_0)
   at Devart.Common.Entity.c3.a()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at Devart.Common.Entity.c3.b()
   at Devart.Data.MySql.Entity.w..ctor(TypeMappingSourceDependencies A_0, RelationalTypeMappingSourceDependencies A_1, c4 A_2)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkRelationalServicesBuilder.<>c.<TryAddCoreServices>b__3_0(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_Model()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.CheckState()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.Include[TEntity,TProperty](IQueryable`1 source, Expression`1 navigationPropertyPath)
(our code from here on)

[编辑] 这是 Devart 团队现已修复的错误,请使用高于 v8.19.1905 的 dotConnect for MySQL 版本

【问题讨论】:

【参考方案1】:

请尝试关闭池(连接字符串中的“Pooling=false;”)或使用 MySqlConnection.ClearAllPools(true) 明确清除池。

更多信息请参考:

https://www.devart.com/dotconnect/mysql/docs/?Devart.Data.MySql~Devart.Data.MySql.MySqlConnection~ConnectionString.html https://www.devart.com/dotconnect/mysql/docs/?Devart.Data.MySql~Devart.Data.MySql.MySqlConnection~ClearAllPools(Boolean).html

【讨论】:

对不起,这没有帮助 修复了 EF Core 中初始连接尝试失败后连接恢复的错误。当 dotConnect for MySQL 的新公共版本可供下载时,我们会通知您。 dotConnect for MySQL v8.19.1905 可供下载:forums.devart.com/viewtopic.php?f=2&t=46768。【参考方案2】:

我已经通过在配置选项操作中提供一个开放的数据库连接来解决这个问题,这是我的解决方法:

 services.AddTransient<DbConnection, MySqlConnection>();
 services.AddDbContext<BusinessContext>((sp, opt) =>
 
      lock (this)
      
          var sql = sp.GetRequiredService<DbConnection>();
          sql.ConnectionString =
              Configuration.GetConnectionString("connectionstring");
          if (!_isConnected)
          
              sql.Open(); // Ensure we can actually get a connection
              _isConnected = true;
          
          opt.UseMySql(sql);
      
 );

如果在 DB 不可用时发生第一次连接尝试,这将引发异常,并阻止 devart 组件尝试创建模型,直到第一次连接成功。这不是很好,我不想这样做,也不能保证成功

【讨论】:

以上是关于如果在 DB 服务器不可用时尝试第一次查询,则 Devart/EFCore 永久失败的主要内容,如果未能解决你的问题,请参考以下文章

当某个表中的数据不可用时查询

如何在出现之前过滤ios推送通知

当原始存储库不可用时,是不是可以将默认存储库添加到 SLES?

如何使用 Azure SQL db 中的存储过程一次性获取查询的所有批次?

无凭证条件下的权限获取

DB2 SELECT COUNT,如果为 NULL,则默认为 0