ASP.Net Core Npgsql 一个操作已经在进行中

ASP.Net Core Npgsql An operation is already in progress

为了重用同一个 DbCommand 并且不在每次我需要在同一个请求中访问数据库时都创建一个新连接,我创建了一个方法来保存 DbCommand 和 returns 如果它以前是实例化:

public static class InformacionInscripcionesViewModel {

        private static NpgsqlConnection _dbConnection;
        private static NpgsqlCommand _dbCommand;

        private static NpgsqlCommand GetDbCommand() {
            InformacionInscripcionesViewModel._dbConnection = InformacionInscripcionesViewModel._dbConnection ?? new NpgsqlConnection("Host=192.168.1.127;Username=siu;Password=123456;Database=guaraniprueba20160816");
            if (InformacionInscripcionesViewModel._dbConnection.State == ConnectionState.Closed)
                InformacionInscripcionesViewModel._dbConnection.Open();

            return InformacionInscripcionesViewModel._dbCommand
                   ?? (InformacionInscripcionesViewModel._dbCommand = new NpgsqlCommand {Connection = InformacionInscripcionesViewModel._dbConnection});
        }
}

如何在模型中使用它的示例:

var dbCommand = InformacionInscripcionesViewModel.GetDbCommand();
dbCommand.CommandText = @"SELECT sga_propuestas.nombre_abreviado AS nombre_carrera, ....";
dbCommand.ExecuteNonQuery();

当我使用它同时向 URL 发出 2 个请求时,它会在 dbCommand.ExecuteNonQuery(); 处抛出异常并显示消息 An operation is already in progress.

我能做些什么来防止这种情况发生? DbCommand 是否应该在每次使用前实例化?对此有任何了解吗?

{System.InvalidOperationException: An operation is already in progress.
   at Npgsql.NpgsqlConnector.StartUserAction(ConnectorState newState)
   at Npgsql.NpgsqlCommand.ExecuteNonQueryInternal()
   at Npgsql.NpgsqlCommand.ExecuteNonQuery()
   at SIUNPAZ.Models.InformacionInscripcionesViewModels.InformacionInscripcionesViewModel.GetTotalesInscripcionesPorMaterias(DateTime fechaDesde, DateTime fechaHasta, String carrera)
   at SIUNPAZ.Controllers.InformacionInscripcionesController.PorMaterias(DateTime fechaDesde, DateTime fechaHasta, String carrera)
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionFilterAsync>d__28.MoveNext()}

… and not instatiating a new connection every time I need to access the DB in the same request

与大多数其他 ADO.NET 实现一样,Npgsql 具有连接池,因此只要您 Dispose() 连接对象,底层连接将被重用,除非存在同时查询。不要修复临时连接池中的错误,只需使用已经提供给您的错误即可。

您不能跨请求共享数据库连接,这实际上是您通过将它们设为静态来执行的操作。可以在单个请求中为多个命令共享一个连接,但它的生命周期应该与请求的生命周期相关联。首先,您可以删除 'static',您的代码应该 运行。您可能想要查看 IoC 容器(Unity、Ninject、StructureMap 等)来为您创建连接,并在您的构造函数中请求它们。大多数都有生命周期管理器,可以自动将对象范围限定为 HTTP 请求。

此外,在 ViewModel 中包含逻辑通常被认为是不好的做法。 ViewModel 不应该有 DbConnections。您应该考虑为数据访问提供服务或将数据库代码移动到控制器。