【问题标题】:Getting SqlTransaction exceptions using Entity Framework with ASP.NET MVC Core使用带有 ASP.NET MVC Core 的实体框架获取 SqlTransaction 异常
【发布时间】:2019-09-17 02:24:09
【问题描述】:

有时(尤其是在多个选项卡中打开同一个网页时)我在 ASP.NET Core 上使用 Entity Framework 保存更改时收到以下异常之一。目前,我在 IIS Express 上本地运行(通过 Visual Studio 2017 调试)。

Microsoft.EntityFrameworkCore.DbContext:Error: An exception occurred in the database while saving changes.
System.InvalidOperationException: This SqlTransaction has completed; it is no longer usable.
   at System.Data.SqlClient.SqlTransaction.ZombieCheck()
   at System.Data.SqlClient.SqlTransaction.Commit()
   ...

Microsoft.EntityFrameworkCore.DbContext:Error: An exception occurred in the database while saving changes.
System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Data.SqlClient.SqlInternalTransaction.Commit()
   at System.Data.SqlClient.SqlTransaction.Commit()
   ...

System.Data.SqlClient.SqlException: The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   ...

以下代码中的SaveChangesAsync()方法被调用时会抛出这些异常:

public async void Remove( int statementId )
{
    Statement statement = _data.Statements.FirstOrDefault( s => s.StatementId == statementId );
    if ( statement != null )
    {
        _data.Statements.Remove( statement );
        await _data.SaveChangesAsync();
    }
}

_dataApplicationDbContext,根据 ASP Core 文档,它可以在控制器中注入依赖项(在这种情况下是在自定义中间存储库类中)并在不包装 using 的情况下重复使用,如过去的。然而,这些错误似乎暗示这不能正常工作......

【问题讨论】:

  • 我以为我找到了问题所在:我的存储库类通过IServiceCollection 注册为AddTransient(),而这是不正确的生命周期。它should be AddScoped()。无论如何,......(一些?)例外仍然存在。
  • 目前,使用非异步SaveChanges()(和AddScoped)时,这些问题似乎已经消失,但我不知道为什么异步会影响这个?
  • 现在我知道这可能与使用异步有关,我发现以下内容:Dependency Injected UserManager is disposing on async call (ASP.NET CORE)

标签: entity-framework asp.net-core-mvc


【解决方案1】:

似乎实体框架连接已断开,因此这是ApplicationDbContext 生命周期的问题。

确保您的存储库类(内部依赖 ApplicationDbContext 的那个)is registered in IServiceCollection as AddScoped() and not AddTransient()

应将实体框架上下文添加到服务容器中 使用Scoped 生命周期。

另外,use async Task instead of async void for asynchronous methods which do not return anything

返回 void 的异步方法没有提供一种简单的方法来通知 调用他们已经完成的代码。

似乎void 导致被调用的对象立即被释放(从而关闭连接),因为没有什么可等待的。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。原来我忘记在对SaveChangesAsync() 的异步调用中使用await

    这似乎会导致与数据库的连接偶尔断开,然后在 SQL Server 级别抛出错误 3902(“COMMIT TRANSACTION 请求没有对应的...”)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-17
      • 2017-09-20
      • 1970-01-01
      • 2011-12-06
      • 1970-01-01
      相关资源
      最近更新 更多