考虑通过将“EnableRetryOnFailure()”添加到“UseMySql”调用来启用瞬态错误弹性

N.A*_*yaz 14 mysql f# asynchronous entity-framework async-await

我有一个基于 F# 的应用程序,我使用 EF-Core 和 MySQL (Pomelo.EntityFrameworkCore.MySql)。我有一个async方法可以更新数据库(MySql)中的数据

let updatePlayerAchievementsAsync (logger:ILogger) (ctx:ReportCacheDbContext) (id: int) = async {
  let! account = ctx.AccountCaches.FirstOrDefaultAsync(fun e -> e.AccountId = id) |> Async.AwaitTask
  if account <> null then
    account.State <- "Closed"
    do! ctx.SaveChangesAsync true |> Async.AwaitTask |> Async.Ignore
    logger.LogInformation("Account{0} updated", id)        
}
Run Code Online (Sandbox Code Playgroud)

当该方法执行到第99个元素时,出现以下错误:

|ERROR|System.InvalidOperationException:An exception has been raised that is likely due to a transient failure. Consider enabling transient error resiliency by adding 'EnableRetryOnFailure()' to the 'UseMySql' call. 
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Connect Timeout expired. All pooled connections are in use.
Run Code Online (Sandbox Code Playgroud)

我尝试遵循第一个错误的建议并尝试添加EnableRetryOnFailure()

member this.ConfigureServices(services: IServiceCollection) =
    services.AddOptions() |> ignore
    services.AddCors() |> ignore
    
    services
        .AddDbContext<ApplicationDbContext>(
            fun (service:IServiceProvider) (dbContext:DbContextOptionsBuilder) ->
                dbContext.UseMySql(profile.DbConnectionToAdmin /*HERE*/)|> ignore)
    ...
Run Code Online (Sandbox Code Playgroud)

我找不到任何关于为 F# 和 MySQL 添加选项的文档,因为所有找到的信息都是用 C# 编写的。也许是已用池的问题(默认 max=100),我接下来写道:

...
do! ctx.SaveChangesAsync true |> Async.AwaitTask |> Async.Ignore
ctx.Database.CloseConnection()
logger.LogInformation("Account{0} updated", id)  
Run Code Online (Sandbox Code Playgroud)

但无论如何问题都没有解决。这是我的新经历F#async我无法理解我做错了什么。有人可以帮我吗?

She*_*hen 13

上面用UseSqlServer()回答了这个问题,这可能有点令人困惑。它将与UseMySql()一起使用,您只需要像下面一样更新您的Startup.cs

我针对Pomelo.EntityFrameworkCore.MySql 版本 5.0.0-alpha.2进行了测试和运行

调整 maxRetryCount、maxRetryDelay 等以满足您的需求。

        services.AddDbContextPool<DBContext>(options =>
        {
            options.UseMySql(
                mySqlConnectionStr, 
                ServerVersion.AutoDetect(mySqlConnectionStr),
                options => options.EnableRetryOnFailure(
                    maxRetryCount: 5,
                    maxRetryDelay: System.TimeSpan.FromSeconds(30),
                    errorNumbersToAdd: null)
                );
        });
Run Code Online (Sandbox Code Playgroud)


小智 8

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EFMiscellanous.ConnectionResiliency;Trusted_Connection=True;ConnectRetryCount=0",
            options => options.EnableRetryOnFailure());
}
Run Code Online (Sandbox Code Playgroud)

  • 答案甚至与 MySql 无关。 (7认同)
  • dafuq 对 MySql 有何作用?`UseSqlServer()` 仅适用于 MSSQL,如果您尝试像操作一样使用 `useMySql()` 方法,您会收到一个错误,因为它的派生略有不同,并且没有 `EnableRetryOnFailure()` 方法,这就是整个过程的地方问题是从哪里来的!!!??? (7认同)
  • 但它是关于 EnableRetryOnFailure() (3认同)
  • 欢迎来到堆栈溢出。虽然此代码可以回答问题,但提供有关此代码为何和/或如何回答问题的附加上下文可以提高其长期价值。[如何回答](https://stackoverflow.com/help/how-to-answer)。亲切的问候。 (2认同)