【问题标题】:Executing SQL store procedure by EF Core 2.2 gets a timeout while executing it successfully in SQL Server Management通过 EF Core 2.2 执行 SQL 存储过程在 SQL Server 管理中成功执行时出现超时
【发布时间】:2020-05-21 06:19:06
【问题描述】:

我有一个奇怪的行为。当我尝试通过 EF Core 2.2 执行 SQL 存储过程时。我得到一个超时(30秒)。但是,当我在 SQL Server Management Studio 中执行相同的过程时,它会成功运行 - 运行大约 1 或 2 秒。

更新:这个问题发生在大约 2 个月前。在此之前,该服务能够运行此过程。

这是我使用的DbContext

public class MyContext : DbContext
{
    public MyContext(string connectionString)
        : base(new DbContextOptionsBuilder().UseSqlServer(connectionString).Options)
    {
    }

    // some DbSets omitted here ...

    public async Task<string> ProcExecuteAsync(string login, string xml)
    {
        // get some data from db (omitted)

        var xmlParameter = new SqlParameter("@XML", SqlDbType.Xml) { Value = xml };
        var xmlOutputParameter = new SqlParameter("@XMLoutput", SqlDbType.Xml) { Direction = ParameterDirection.Output };

        await Database.ExecuteSqlCommandAsync(
            "MyProc_set @idUser=@idUser,@XML=@XML,@XMLoutput=@XMLoutput OUT",
            new SqlParameter[] { userIdParameter, xmlParameter, xmlOutputParameter });

        return (string)xmlOutputParameter.Value;
    }
}

然后我有一个处理程序(我使用Mediator 库):

public class AddToClientCommandHandler : IRequestHandler<AddToClientCommand, AddToClientResponse>
{
    private readonly IContextBuilder _contextBuilder; 

    public AddToClientCommandHandler(IContextBuilder contextBuilder)
    {
        _contextBuilder = contextBuilder;
    }

    public async Task<AddToClientResponse> Handle(AddToClientCommand command, CancellationToken cancellationToken)
    {
        using (var context = _contextBuilder.CreateMyContext())
        {
            // getting some data from db (omitted)

            // generate xmlRequest (omitted)

            var result = await context.ProcExecuteAsync(command.Login, xmlRequest);
            return new AddToClientResponse(result);
        }
    }
}

这是ContextBuilder

public class ContextBuilder : IContextBuilder
{
    private readonly IOptions<ConnectionStrings> _connectionStrings;

    public ContextBuilder(IOptions<ConnectionStrings> connectionStrings)
    {
        _connectionStrings = connectionStrings;
    }

    public MyContext CreateMyContext()
    {
        var result = new MyContext(_connectionStrings.Value.Entities);
        return result;
    }
}

我是这样注册的:

public static class ApplicationContextBuilderExtension
{
    public static void AddApplicationContextBuilder(this IServiceCollection services)
    {
        services.AddSingleton<IContextBuilder, ContextBuilder>();
    }
}

有没有可能是我注册ContextBuilder时使用了AddSingleton造成的问题?

谁能告诉我如何以及在哪里调查问题?

【问题讨论】:

  • 您的处理程序正在调用CreateLMContext,但您的构建器有CreateMyContext。这只是示例代码中的错字/错误吗?
  • 是的,这是一个错字。谢谢,我编辑了。
  • 您能否检查(从异常堆栈跟踪或 EF Core 日志记录)异常是由 db 连接打开触发还是由 db 命令执行触发的?
  • @Ivan,看起来异常是由 db 命令执行触发的:“ClassName”:“System.Data.SqlClient.SqlException”,“Message”:“Timeout expired。超时时间已过之前操作完成或服务器没有响应。",

标签: c# sql-server asp.net-core stored-procedures ef-core-2.2


【解决方案1】:

问题是否可能来自我在注册时使用 AddSingleton 上下文构建器?

不,因为 ContextBuilder 中的一种方法不执行数据库操作,并且不会一直返回相同的上下文。

但是当我在 SQL Server Management Studio 中执行相同的过程时,它会运行 成功

需要多长时间?据我所知,SSMS 不会施加超时限制,这会告诉您为什么没有超时。 EfCore 限制为 30 秒,除非您更改它 - 根据文档,这很简单,但必须完成。

这里的概念是 SSMS 比 EfCore 更多地用于批量操作,在 EfCore 中,30 秒的操作可能被视为错误 - 在极少数情况下,您希望/需要更长的超时时间,请重新配置 dbcontext。

【讨论】:

  • 正确,EF Core 有 30 秒的超时。 SSMS 仅在 1 或 2 秒内运行此过程。所以,差距太大了。第一次,这个问题发生在大约 2 个月前。在此之前,该服务能够运行此过程。
  • 好吧,如果您有其他信息,您可以考虑下次花更多时间来制定您的问题。
【解决方案2】:

我也遇到了同样的问题。我浏览了以下链接:

Stored procedure slow when called from web, fast from Management Studio

我已经像这样修改了sp:

改变程序 [dbo].[sproc] @param1 整数, 作为 SELECT * FROM Table WHERE ID = @param1

改变程序 [dbo].[sproc] @param1 整数, 作为 声明@param1a int 设置@param1a = @param1 SELECT * FROM Table WHERE ID = @param1a

对我来说,它工作正常。

【讨论】:

    猜你喜欢
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多