简体   繁体   English

.NET 5 EF Core SaveChangesAsync 因错误而挂起

[英].NET 5 EF Core SaveChangesAsync hangs on errors

Despite there are many results for this question none have really given me a clear answer.尽管这个问题有很多结果,但没有一个真正给我一个明确的答案。

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)每次我尝试通过 AddAsync 和 SaveChangesAsync 方法插入错误数据(例如重复的主键)时,我都会看到以下日志:Failed execution DbCommand (15ms)

I also see the error on the SQL PROFILER and it very clear it's a primary key conflict.我还在 SQL PROFILER 上看到了错误,很明显这是主键冲突。 In these cases the SaveChangesAsync does not throw any error.在这些情况下,SaveChangesAsync 不会引发任何错误。 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.它只是无限期挂起,导致 memory 泄漏,最终应用程序崩溃,我尝试用 try catch 包装 savechanges 无济于事。 and even added a cancellation token to auto cancel after 2 seconds and even that did not stop the hang.甚至添加了一个取消令牌以在 2 秒后自动取消,即使这样也没有停止挂起。 The result is always a never ending HTTP request that never returns a response to the client.结果始终是永不结束的 HTTP 请求,该请求永远不会向客户端返回响应。 *I also tried running the savechangesasync without the configure await and the result is the same. *我也尝试在没有配置等待的情况下运行 savechangesasync,结果是一样的。

DI for context and repository:用于上下文和存储库的 DI:

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

services.AddScoped<IRepository, EfRepository>();

The Controller Method: Controller 方法:

[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);
}

The addasync is the caller: addasync 是调用者:

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:根据要求:整个上下文 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. *上下文的生命周期可能与它无关,我在每个生命周期都重现了这个问题。

Here is the callstack:这是调用堆栈: 调用堆栈

*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.当在 savechanges 中手动抛出错误时,它会正确冒泡。 In another project that shares the same DLLs, the SaveChanges throws an error that bubbles up correctly, also in Async methods.在另一个共享相同 DLL 的项目中,SaveChanges 会抛出一个正确冒泡的错误,在 Async 方法中也是如此。

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 has been giving be the hard time all along. Serilog 一直以来都是艰难的时期。 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!感谢每一位评论并试图帮助我的人,非常感谢!

I ended up ditching Serilog and using Seq directly with ILogging extension and everything now works fine!我最终放弃了 Serilog,直接将 Seq 与 ILogging 扩展一起使用,现在一切正常!

In the comments you say that you inject your db context as transient.在评论中,您说您将数据库上下文注入为瞬态。 I would suggest to inject it as scoped, this would ensure you are using the "same" dbcontext per request in your whole data flow.我建议将其作为作用域注入,这将确保您在整个数据流中的每个请求都使用“相同”的 dbcontext。

Using different dbcontext, as it would be if using transient lifetime, in different consumers in the same request for your data access flow could lead to strange behaviours, like this使用不同的 dbcontext,就像使用瞬态生命周期一样,在对数据访问流的同一请求中的不同消费者中可能会导致奇怪的行为,例如

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM