.NET 5 EF Core SaveChangesAsync因错误而挂起 [英] .NET 5 EF Core SaveChangesAsync hangs on errors

查看:153
本文介绍了.NET 5 EF Core SaveChangesAsync因错误而挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽管这个问题有很多结果,但没有一个能给我一个明确的答案.

Despite there are many results for this question none have really given me a clear answer.

每次我尝试通过AddAsync和SaveChangesAsync方法插入错误的数据(例如重复的主键)时,都会看到以下日志:无法执行DbCommand(15毫秒)

Every time I try to insert faulty data such as a duplicate primary key, via the AddAsync and SaveChangesAsync methods, I see this log: Failed executing DbCommand (15ms)

我还看到了SQL PROFILER上的错误,很明显这是主键冲突.在这些情况下,SaveChangesAsync不会引发任何错误!它只是无限期地挂起,导致内存泄漏,最终导致应用程序崩溃.我尝试用try catch来包装savechanges都没有用,甚至添加了取消令牌以在2秒后自动取消,即使那样也没有停止挂起.结果始终是一个永无止境的HTTP请求,该请求从不向客户端返回响应.*我还尝试了在不等待配置的情况下运行savechangesasync,结果是相同的.

I also see the error on the SQL PROFILER and it very clear it's a primary key conflict. In these cases the SaveChangesAsync does not throw any error! It just hangs indefinitely causing a memory leak and eventually the app crashes. I tried wrapping the savechanges with a try catch to no avail, and even added a cancellation token to auto cancel after 2 seconds and even that did not stop the hang. The result is always a never ending HTTP request that never returns a response to the client. *I also tried running the savechangesasync without the configure await and the result is the same.

用于上下文和存储库的DI:

DI for context and repository:

        services.AddDbContext<SalesDBContext>(o => 
            o.UseSqlServer(appSettings.ConnectionString)
            .EnableDetailedErrors(true)
            .EnableSensitiveDataLogging()
        , ServiceLifetime.Scoped);

services.AddScoped<IRepository, EfRepository>();

控制器方法:

[HttpPost]
public async Task<IActionResult> Post([FromBody] SomeRequest request)
{
    if (ModelState.IsValid)
    {
        var data = await _service.AddAsync(request);
        return Ok(data);
    }
    return BadRequest(ModelState.Values);
}

addasync是调用者:

The addasync is the caller:

public class EfRepository : IRepository
{
    private readonly SalesDBContext _dbContext;

    public EfRepository(SalesDBContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<int> AddAsync<T>(T entity) where T : Entity
    {
        _dbContext.Set<T>().Add(entity);
        return await _dbContext.SaveChangesAsync();
    }
}

我通过检查是否存在违规问题解决了该问题,但这不能解决根本的问题,即目前我无法记录这些错误,并且如果再次发生该错误将破坏网站.

I fixed the issue by checking there are no violations, but this does not solve the root problem that currently it is impossible for me to log these errors and if this happens again somewhere it will destroy the website.

根据请求:整个上下文类:

As per request: The entire context class:

    public class SalesDBContext : DbContext
{
    public DbSet<Entity> Entities { get; set; }


    public SalesDBContext(DbContextOptions<SalesDBContext> options) : base(options)
    {

    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.ApplyConfigurationsFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());

        foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
        {
            relationship.DeleteBehavior = DeleteBehavior.Restrict;
        }
    }
    //This is the savechanges being called.
    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        int result = await base.SaveChangesAsync(cancellationToken); 
        //Hangs here on primary key conflict error
        return result;
    }
}

*上下文的生命周期可能与它无关,我在每个生命周期中都再现了这个问题.

*The lifetime of the context probably has nothing to do with it, I reproduced the issue with every lifetime.

这是调用栈:

*更多信息:使用非异步方法保存时,也会发生挂起.当在savechanges中手动抛出错误时,它会正确冒出.在共享相同DLL的另一个项目中,SaveChanges也会引发错误,并且在Async方法中也会冒出正确的气泡.

*More information: The hang occurs also when saving with the non Async method. When manually throwing an error in the savechanges it bubbles up correctly. In another project that shares the same DLLs, the SaveChanges throws an error that bubbles up correctly, also in Async methods.

推荐答案

我终于找到了问题!我坐下来,开始每次只删除一行代码,直到找到罪魁祸首!

I have finally found the Issue!! I sat down and just started removing code one line at a time until I found the culprit!

.UseSerilog((hostingContext, loggerConfiguration) => {
    loggerConfiguration
    .ReadFrom.Configuration(hostingContext.Configuration)
    .Enrich.FromLogContext()
    .Enrich.WithProperty("ApplicationName", typeof(Program).Assembly.GetName().Name)
    .Enrich.WithProperty("Environment", hostingContext.HostingEnvironment);
#if DEBUG
    loggerConfiguration.Enrich.WithProperty("DebuggerAttached", Debugger.IsAttached);
#endif
});

Serilog一直很艰难.没有错误指向日志记录有问题的方向,因为所有日志都可以工作.因此,我只是一个接一个地删除了功能,直到删除该功能时,挂起停止了,异常开始冒泡了.

Serilog has been giving be the hard time all along. There were no errors pointing in the direction that something is wrong with the logging because all the logs work. So I just removed features one after another until when I removed this the hanging stopped and exceptions started to bubble up.

感谢您发表评论并尝试帮助我的每一个人,非常感谢!

Thank you for every one who commented and tried to help me, it is much appreciated!

我最终放弃了Serilog,并直接将Seq与ILogging扩展结合使用,现在一切正常!

I ended up ditching Serilog and using Seq directly with ILogging extension and everything now works fine!

这篇关于.NET 5 EF Core SaveChangesAsync因错误而挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆