SetCommandTimeout 的执行不适用于 PostgreSQL 的 EF Core 5
Execution of SetCommandTimeout not working with EF Core 5 for PostgreSQL
我遇到了一个问题,当我 SetCommandTimeout 时好像该方法无法正常工作。
我使用 PostgreSQL 作为数据库,对于 EntityFramework 核心,我使用 Npgsql.EntityFrameworkCore.PostgreSQL
版本 5.0.5.1
在代码中,我像这样 context.Database.SetCommandTimeout(1);
将超时设置为 1 秒,并设置了一个秒表来检查花费了多少时间,但 ElapsedMiliseconds 总是 return 大约 15000 毫秒到 16000 毫秒。所以 SetCommandTimeout(1)
显然不起作用。
我也试过用context.Database.SetCommandTimeout(TimeSpan.FromSeconds(1));
也不行。
还有一件事,我只想为特定请求设置超时。所以另一个请求将有默认超时。
这是我的代码:
[Route("api/[controller]")]
[ApiController]
public class TestController : Controller
{
private readonly DatabaseContext context;
public TestController(DatabaseContext context)
{
this.context = context;
}
[AllowAnonymous]
[HttpGet]
public async Task<IActionResult> Test()
{
var sw = Stopwatch.StartNew();
try
{
context.Database.SetCommandTimeout(1);
var test = await context.Test.FirstOrDefaultAsync();
return Ok();
}
catch (Exception)
{
return BadRequest();
}
finally
{
sw.Stop();
var elapsed = sw.ElapsedMilliseconds; // always return around 15000ms to 16000ms
}
}
}
这是我在 Startup.Cs
中注册的方式
services.AddDbContext<DatabaseContext>(options =>
{
options.UseNpgsql(ConnectionString);
});
我是不是漏了什么?
提前致谢
命令超时是允许在数据库服务器上执行查询/命令的时间。计时器在数据库服务器收到请求时启动。由于网络吞吐量或其他限制 - 包括您的网络服务器上的资源耗尽,您的 end-to-end 往返时间可能比命令超时时间长。
Command Timeout: The time to wait (in seconds) while trying to execute a command before terminating the attempt and generating an error.
Source
Google 了一下,发现了与该库相关的问题。
基于此forum post,问题似乎来自源代码,设置被忽略了。
尝试 set-up 创建数据库上下文中的命令超时 而不是在使用之前。
另一个在 github repository。
此问题的解决方案是升级到最新版本的驱动程序。
另一个来自 github.
此问题的解决方法是 在创建上下文期间修改连接字符串:
if (!connectionString.Contains("CommandTimeout"))
{
connectionString += $";CommandTimeout=120";
}
编辑(在 OP 提到他想在单个请求上使用它之后): 我建议通过创建其他数据库上下文并修改其连接字符串(如上所述).这样你就可以执行 short/long 运行 命令。但是,这带来了与多个 DB-context 和可能的数据不匹配相关的其他问题。需谨慎处理。
我遇到了一个问题,当我 SetCommandTimeout 时好像该方法无法正常工作。
我使用 PostgreSQL 作为数据库,对于 EntityFramework 核心,我使用 Npgsql.EntityFrameworkCore.PostgreSQL
版本 5.0.5.1
在代码中,我像这样 context.Database.SetCommandTimeout(1);
将超时设置为 1 秒,并设置了一个秒表来检查花费了多少时间,但 ElapsedMiliseconds 总是 return 大约 15000 毫秒到 16000 毫秒。所以 SetCommandTimeout(1)
显然不起作用。
我也试过用context.Database.SetCommandTimeout(TimeSpan.FromSeconds(1));
也不行。
还有一件事,我只想为特定请求设置超时。所以另一个请求将有默认超时。
这是我的代码:
[Route("api/[controller]")]
[ApiController]
public class TestController : Controller
{
private readonly DatabaseContext context;
public TestController(DatabaseContext context)
{
this.context = context;
}
[AllowAnonymous]
[HttpGet]
public async Task<IActionResult> Test()
{
var sw = Stopwatch.StartNew();
try
{
context.Database.SetCommandTimeout(1);
var test = await context.Test.FirstOrDefaultAsync();
return Ok();
}
catch (Exception)
{
return BadRequest();
}
finally
{
sw.Stop();
var elapsed = sw.ElapsedMilliseconds; // always return around 15000ms to 16000ms
}
}
}
这是我在 Startup.Cs
中注册的方式services.AddDbContext<DatabaseContext>(options =>
{
options.UseNpgsql(ConnectionString);
});
我是不是漏了什么?
提前致谢
命令超时是允许在数据库服务器上执行查询/命令的时间。计时器在数据库服务器收到请求时启动。由于网络吞吐量或其他限制 - 包括您的网络服务器上的资源耗尽,您的 end-to-end 往返时间可能比命令超时时间长。
Command Timeout: The time to wait (in seconds) while trying to execute a command before terminating the attempt and generating an error. Source
Google 了一下,发现了与该库相关的问题。
基于此forum post,问题似乎来自源代码,设置被忽略了。
尝试 set-up 创建数据库上下文中的命令超时 而不是在使用之前。
另一个在 github repository。
此问题的解决方案是升级到最新版本的驱动程序。
另一个来自 github.
此问题的解决方法是 在创建上下文期间修改连接字符串:
if (!connectionString.Contains("CommandTimeout"))
{
connectionString += $";CommandTimeout=120";
}
编辑(在 OP 提到他想在单个请求上使用它之后): 我建议通过创建其他数据库上下文并修改其连接字符串(如上所述).这样你就可以执行 short/long 运行 命令。但是,这带来了与多个 DB-context 和可能的数据不匹配相关的其他问题。需谨慎处理。