【问题标题】:Stored procedure not executing correctly through entity framework存储过程未通过实体框架正确执行
【发布时间】:2016-02-25 16:21:53
【问题描述】:

当我在 SQL Management Studio 中运行以下存储过程时,它按预期运行,大约需要 5 分钟才能完成。

exec [dbo].[sproc] '2016-02-01', '2016-02-29'

但是,当使用 Entity Framework 运行时,它似乎需要 1 秒,并且实际上并没有做它应该做的事情,即使我传递了相同的参数

这可能是配置问题吗?

我将连接字符串名称传递给DbContext 构造函数,由于超时,上述内容正在线程中运行

new Thread(new ThreadStart ( delegate ()
{
    using (var context = new MyDbContext())
    {
        var d1 = new SqlParameter("Date_From", dateFrom);
        var d2 = new SqlParameter("Date_To", dateTo);
        int result = context.Database.ExecuteSqlCommand("exec [dbo].[sproc] @Date_From, @Date_To", d1, d2);
    }
})).Start();

-- 更新--

存储过程需要一个日期时间,虽然我可以使用字符串在本地运行它(它会将其转换为日期时间),但它不会通过 ExecuteSqlCommand 运行,除非我将参数作为 DateTimes 传递。当然,如果我传递一个 datetime 参数,它应该知道哪些是天、月和年?

ALTER PROCEDURE [dbo].[sproc]
(
    @Date_From  AS DATETIME,
    @Date_To    AS DATETIME
)

-- 更新--

通过 SQL Profiler 检查时正在执行以下操作

exec sp_executesql N'exec [dbo].[sproc] @Date_From, @Date_To',N'@Date_From datetime,@Date_To datetime',@Date_From='2016-02-01 00:00:00',@Date_To='2016-02-29 00:00:00'

如果我在 SQL Server 管理器中手动运行,我会收到以下错误:

将数据类型 varchar 转换为 datetime 时出错。

用户/安全/数据库设置?

【问题讨论】:

  • 您能否让分析器在数据库上运行并查看 EF 正在传递什么查询?
  • @Jay 它似乎正在转换为 nvarchar? (我认为)@Date_From=N'29/02/2016',@Date_To=N'01/02/2016'
  • @Jay 如果我在 sql 管理上运行它,它会运行 exec [dbo].[sproc] '01-02-2016', '29-02-2016'
  • 存储过程是否需要一个日期时间值?尝试将其作为日期时间值而不是字符串传递
  • “不是它应该做的”是什么意思?您正在另一个线程上运行它,这就是为什么您看不到它在搅拌的原因。委托返回 void,因此没有输出。你是说它应该在数据库中产生没有发生的副作用吗?如果你把它从线程中取出怎么办(无论如何这很糟糕,使用ExecuteSqlCommandAsync())。

标签: c# sql-server entity-framework stored-procedures


【解决方案1】:

ToShortDateString() 生成的日期可能存在问题,因为它是 not going to format the date,例如 2016-02-01。它将根据其运行的文化生成一个日期,因此将从上面的链接中输出如下内容:

//       Displaying short date for en-US culture:
//       6/1/2009 (Short Date String)

在使用.ToShortDateString() 时,SQL Server 可能无法正确格式化此值 ('2016-02-01'),它可能会错误地获取日期和月份,这可以解释您的意外结果。

可以在 SQL Server Management Studio 中运行的快速测试:

SELECT CAST('01/02/2016' AS DATE)

它是否产生:2016-01-022016-02-01

您还可以在此行使用断点调试应用程序:

int result = context.Database.ExecuteSqlCommand("exec [dbo].[sproc] @Date_From, @Date_To", d1, d2);

您可以检查参数d1d2中的值,以确保格式符合您的预期。

【讨论】:

  • @iswinky 我建议调试我的答案中发布的应用程序,以检查发送到 SQL 的格式是 01/02/2016 还是 02/01/2016
  • @Date_From=N'29/02/2016',@Date_To=N'01/02/2016' 是 sql profiler 和调试器中显示的内容
  • @iswinky 尝试将该格式的日期传递给您的存储过程
【解决方案2】:

根据您的陈述:

new Thread(new ThreadStart ( delegate ()
{
    using (var context = new MyDbContext())
    {
        var d1 = new SqlParameter("Date_From", dateFrom.ToShortDateString());
        var d2 = new SqlParameter("Date_To", dateTo.ToShortDateString());
        int result = context.Database.ExecuteSqlCommand("exec [dbo].[sproc] @Date_From, @Date_To", d1, d2);
    }
})).Start();

ALTER PROCEDURE [dbo].[sproc]
(
    @Date_From  AS DATETIME,
    @Date_To    AS DATETIME
)

您不应该这样做 dateFrom.ToShortDateString());dateTo... - 您的 dateFromdateTo 已经是日期时间,正如 SP 所要求的那样。您当前正在将 string 传递给 datetime 参数。解决这个问题,我认为你应该会很好。

另外,这是闰年,你能有一些奇怪的日期数学逻辑不考虑这一点吗?

【讨论】:

  • 我已尝试传递日期时间值,但仍然无法正常工作
【解决方案3】:

存储过程似乎仅在日期时间格式化为 ISO8601 时才执行。这是通过使用“s”作为参数调用 ToString 来实现的

var d1 = new SqlParameter("Date_From", dateFrom.ToString("s"));
var d2 = new SqlParameter("Date_To", dateTo.ToString("s"));

结果

2016-02-01T12:00:00

【讨论】:

    【解决方案4】:

    我遇到了类似的问题,我得到了异常,

    将数据类型 nvarchar 转换为日期时间时出错。

    我不得不将 sql 字符串更改为

    int result = context.Database.ExecuteSqlCommand("exec [dbo].[sproc] @Date_From = @Date_From, @Date_To = @Date_To", d1, d2);
    

    由于某种原因,在添加 @Parameters 时,我需要将它们设置为等于 SqlParameter 名称。所以@Date_From, @Date_To = @Date_To..."

    【讨论】:

      猜你喜欢
      • 2013-10-31
      • 1970-01-01
      • 2016-12-28
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 2012-02-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多