簡體   English   中英

.NET 5 EF Core SaveChangesAsync 因錯誤而掛起

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

盡管這個問題有很多結果,但沒有一個真正給我一個明確的答案。

每次我嘗試通過 AddAsync 和 SaveChangesAsync 方法插入錯誤數據(例如重復的主鍵)時,我都會看到以下日志:Failed execution DbCommand (15ms)

我還在 SQL PROFILER 上看到了錯誤,很明顯這是主鍵沖突。 在這些情況下,SaveChangesAsync 不會引發任何錯誤。 它只是無限期掛起,導致 memory 泄漏,最終應用程序崩潰,我嘗試用 try catch 包裝 savechanges 無濟於事。 甚至添加了一個取消令牌以在 2 秒后自動取消,即使這樣也沒有停止掛起。 結果始終是永不結束的 HTTP 請求,該請求永遠不會向客戶端返回響應。 *我也嘗試在沒有配置等待的情況下運行 savechangesasync,結果是一樣的。

用於上下文和存儲庫的 DI:

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

services.AddScoped<IRepository, EfRepository>();

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

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

我通過檢查沒有違規來解決問題,但這並不能解決根本問題,即目前我無法記錄這些錯誤,如果這種情況再次發生在某個地方,它將破壞網站。

根據要求:整個上下文 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;
    }
}

*上下文的生命周期可能與它無關,我在每個生命周期都重現了這個問題。

這是調用堆棧: 調用堆棧

*更多信息:使用非異步方法保存時也會發生掛起。 當在 savechanges 中手動拋出錯誤時,它會正確冒泡。 在另一個共享相同 DLL 的項目中,SaveChanges 會拋出一個正確冒泡的錯誤,在 Async 方法中也是如此。

我終於找到問題了!! 我坐下來,開始一次一行地刪除代碼,直到找到罪魁禍首!

.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,直接將 Seq 與 ILogging 擴展一起使用,現在一切正常!

在評論中,您說您將數據庫上下文注入為瞬態。 我建議將其作為作用域注入,這將確保您在整個數據流中的每個請求都使用“相同”的 dbcontext。

使用不同的 dbcontext,就像使用瞬態生命周期一樣,在對數據訪問流的同一請求中的不同消費者中可能會導致奇怪的行為,例如

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM