英文:
NpgsqlOperationInProgressException while querying postgres database
问题
每当我尝试运行查询时,都会出现以下异常:Npgsql.NpgsqlOperationInProgressException (0x80004005): A command is already in progress.
我正在使用 Dapper 和 PostgreSQL。以下是我的 CarsService 数据访问代码:
public class CarsService : ICarsService
{
private readonly IDbConnection _connection;
public CarsService(IDbConnection connection) => _connection = connection;
public Task<IEnumerable<int>> GetAvailableCarsIdsAsync(int carModelId, DateTime startDate, DateTime endDate)
{
return _connection.QueryAsync<int>(@"" select c.id from cars c where c.car_model_id = @CarModelId and c.id not in ( select r.car_id from rentals r where r.car_id = c.id and r.start_date <= @EndDate and r.end_date >= @StartDate ) "", new { CarModelId = carModelId, StartDate = startDate, EndDate = endDate });
}
public Task<IEnumerable<int>> GetCarIdsAsync(int carModelId)
{
return _connection.QueryAsync<int>(@"" select c.id from cars c where c.car_model_id = @CarModelId "", new { CarModelId = carModelId });
}
}
这是调用服务的方法:
public async Task<IEnumerable<GetCarModelResponse>> Handle(GetCarModelsQuery query, CancellationToken cancellationToken)
{
var carModels = await _carModelsService.GetAsync(query);
return await Task.WhenAll(carModels.Select
(
async carModel =>
{
var availableCarIds = await _carsService.GetAvailableCarsIdsAsync(carModel.Id, query.StartDate, query.EndDate);
return new GetCarModelResponse
(
carModel.Id,
carModel.Model,
carModel.Color,
availableCarIds.Count(),
availableCarIds,
await _carsService.GetCarIdsAsync(carModel.Id)
);
}));
}
IDbConnection
被注入为瞬态,将其注入为范围或单例并未解决此问题。 (builder.Services.AddTransient<IDbConnection>(_ => new NpgsqlConnection("连接字符串"));
)
如何解决这个问题?
谢谢
英文:
Whenever i try to run query i get this exception: Npgsql.NpgsqlOperationInProgressException (0x80004005): A command is already in progress.
I'm using Dapper and PostgreSQL. Here is my code for data access in CarService:
public class CarsService : ICarsService
{
private readonly IDbConnection _connection;
public CarsService(IDbConnection connection) => _connection = connection;
public Task<IEnumerable<int>> GetAvailableCarsIdsAsync(int carModelId, DateTime startDate, DateTime endDate)
{
return _connection.QueryAsync<int>("""
select c.id
from cars c
where c.car_model_id = @CarModelId
and c.id not in (
select r.car_id
from rentals r
where r.car_id = c.id
and r.start_date <= @EndDate
and r.end_date >= @StartDate
)
""", new { CarModelId = carModelId, StartDate = startDate, EndDate = endDate });
}
public Task<IEnumerable<int>> GetCarIdsAsync(int carModelId)
{
return _connection.QueryAsync<int>("""
select c.id
from cars c
where c.car_model_id = @CarModelId
""", new { CarModelId = carModelId });
}
}
Here is the method, that calls service:
public async Task<IEnumerable<GetCarModelResponse>> Handle(GetCarModelsQuery query, CancellationToken cancellationToken)
{
var carModels = await _carModelsService.GetAsync(query);
return await Task.WhenAll(carModels.Select
(
async carModel =>
{
var availableCarIds = await _carsService.GetAvailableCarsIdsAsync(carModel.Id, query.StartDate, query.EndDate);
return new GetCarModelResponse
(
carModel.Id,
carModel.Model,
carModel.Color,
availableCarIds.Count(),
availableCarIds,
await _carsService.GetCarIdsAsync(carModel.Id)
);
}));
}
IDbConnection
is injected as transient, injecting it as scoped or singleton didn't solve the issue. (builder.Services.AddTransient<IDbConnection>(_ => new NpgsqlConnection("connection string"));
)
How can I fix this?
Thanks
答案1
得分: 1
Here is the translated content you provided:
正如我在评论中写的那样:不要重复使用连接!
一个可工作的CarsService可以如下所示:
public class CarsService : ICarsService
{
private readonly string connectionString;
public CarsService(string connectionString) => this.connectionString = connectionString;
public Task<IEnumerable<int>> GetAvailableCarsIdsAsync(int carModelId, DateTime startDate, DateTime endDate)
{
using (var connection = new NpgsqlConnection(connectionString))
{
return connection.QueryAsync<int>(@"
select c.id
from cars c
where c.car_model_id = @CarModelId
and c.id not in (
select r.car_id
from rentals r
where r.car_id = c.id
and r.start_date <= @EndDate
and r.end_date >= @StartDate
)
", new { CarModelId = carModelId, StartDate = startDate, EndDate = endDate });
}
}
public Task<IEnumerable<int>> GetCarIdsAsync(int carModelId)
{
using (var connection = new NpgsqlConnection(connectionString))
{
return connection.QueryAsync<int>(@"
select c.id
from cars c
where c.car_model_id = @CarModelId
", new { CarModelId = carModelId });
}
}
}
这与Postgres紧密耦合,因此您可能希望创建一个用于创建连接的工厂。然后,您可以选择注入该工厂,使其独立于数据库实现,并在那里处理连接字符串。
连接会放回连接池,并且创建连接的开销非常小,因此请始终在查询代码周围创建和处理连接。
英文:
As I wrote in the comment: Don't reuse connections!
A working CarsService could look like this:
public class CarsService : ICarsService
{
private readonly string connectionString;
public CarsService(string connectionString) => this.connectionString = connectionString;
public Task<IEnumerable<int>> GetAvailableCarsIdsAsync(int carModelId, DateTime startDate, DateTime endDate)
{
using (var connection = new NpgsqlConnection(connectionString))
{
return connection.QueryAsync<int>("""
select c.id
from cars c
where c.car_model_id = @CarModelId
and c.id not in (
select r.car_id
from rentals r
where r.car_id = c.id
and r.start_date <= @EndDate
and r.end_date >= @StartDate
)
""", new { CarModelId = carModelId, StartDate = startDate, EndDate = endDate });
}
}
public Task<IEnumerable<int>> GetCarIdsAsync(int carModelId)
{
using (var connection = new NpgsqlConnection(connectionString))
{
return _connection.QueryAsync<int>("""
select c.id
from cars c
where c.car_model_id = @CarModelId
""", new { CarModelId = carModelId });
}
}
}
This is tightly coupled to Postgres, so you might want to make a factory for creating the connection. You can then choose to inject the factory and have it independent of the database implementation and have the conenction string handled there.
Connections are put back in the connection pool and there is very little overhead in creating a connection, so always create and dispose it around your query code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论