TL; DR - SQL存储过程的函数导入返回错误的数据;所有其他调用存储过程的方法都会返回正确的数据。
我的SQL Server 2008 R2服务器中有一个存储过程,其中包含以下签名
ALTER PROCEDURE [dbo].[GetCrashCountByTime]
@start_date datetime,
@end_date datetime,
@moving_avg bit = 0,
@issue_id int = null,
@granularity int -- Either 1, 2, 3, 4, or 5 for Minute, Hour, Day, Month, Year grouping
-- Other inputs removed for brevity
WITH RECOMPILE
AS
BEGIN
-- ...SQL goes here...
END
SQL的示例调用如下所示:
DECLARE @return_value int
EXEC @return_value = [dbo].[GetResultsByTime]
@start_date = '2013-01-14',
@end_date = '2013-01-16',
@issue_id = 1637,
@granularity = 2 -- equivalent to grouping by Hour
SELECT 'Return Value' = @return_value
GO
time | count | avg
-----------------------------------------
2013-01-14 00:00:00.0000000 | 2 | 0
2013-01-14 01:00:00.0000000 | 1 | 0
2013-01-14 02:00:00.0000000 | 1 | 0
2013-01-14 03:00:00.0000000 | 1 | 0
...
关键是@granularity参数确定结果的分组方式 - 按分钟,小时,日,月或年。例如,通过稍微改变调用以使用Date(3),我得到不同的结果(如预期的那样):
DECLARE @return_value int
EXEC @return_value = [dbo].[GetResultsByTime]
@start_date = '2013-01-14',
@end_date = '2013-01-16',
@issue_id = 1637,
@granularity = 3
SELECT 'Return Value' = @return_value
GO
time | count | avg
-----------------------------------------
2013-01-14 00:00:00.0000000 | 21 | 0
2013-01-15 00:00:00.0000000 | 80 | 0
2013-01-16 00:00:00.0000000 | 0 | 0
...
(暂时忽略平均值,这是无关紧要的)。
我已经验证了当我以这种方式直接从SQL调用它时该函数正在工作。
我正在使用此存储过程使用Entity Framework插件(EF版本4.0.0.0)绘制MVC应用程序中的一些数据。首先,我使用数据库中的更改更新了.edmx文件。我打开了Model Explorer并为GetResultsByTime添加了一个Function Import,使用向导自动生成一个新的Complex Type GetResultsByTime_Result。但是,当我使用生成的函数时,我得到的结果就好像我已经通过'Day'来传递粒度而不是我指定的。例如,
用C#代码调用SP:
var data = db.GetResultsByTime(param.StartDate, param.EndDate, param.IssueId, param.Granularity).ToList(); // param.Granularity is an Enum value, in this case GranularityType.Hour
// data has only 2 entries, instead of 24 or so as expected
当我使用Server Explorer执行存储过程时,我再次得到正确的结果:
Running [dbo].[GetCrashCountByTime] ( @start_date = 2013-01-14, @end_date = 2013-01-16, @issue_id = 1637, @granularity = 2 ).
day crash_count avg_count
------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2013-01-14 00:00:00.0000000 2 0
2013-01-14 01:00:00.0000000 1 0
2013-01-14 02:00:00.0000000 1 0
有人有什么想法吗?我已经尝试将@granularity添加到定义存储过程的SELECT中,以确保我在SQL中获得了与我期望的相同的值,并且它总是返回我传入的相同值,只有其余数据为虽然我已经过了3天(白天)。
我为冗长而道歉,我只想确保不遗漏任何重要细节。
编辑:在Matthew的建议中,我通过包括Stack Exchange MiniProfiler开启了分析。在从网站请求数据后,Profiler显示生成的SQL为:ExecuteStoreCommands CreateFunctionObjectResult ExecuteFunction ExecuteFunction GetCrashCountByTime CrashesByDay
DECLARE @start_date DateTime2 = '2013-01-01T00:00:00',
@end_date DateTime2 = '2013-01-17T09:14:00',
@issue_id int = 1637,
@granularity int = 2
[dbo].[GetCrashCountByTime]
我选择了“小时”,如图所示,解析为2。
编辑2:
还有另一个输入变量@moving_avg位,用于控制是否计算平均值。所以存储过程中有一个部分,如:
CREATE PROCEDURE [dbo].[GetResultsByTime]
-- ...
@moving_avg bit = 0,
-- ...
IF @moving_avg = 0
BEGIN
-- Do calculation without average
END
ELSE
BEGIN
-- Calculate average
END
在查看生成的SQL时,我看到@moving_avg被设置为null。我将程序更改为检查null或0:
IF @moving_avg = 0 OR @moving_avg IS NULL
BEGIN
-- Do calculation without average
END
现在它似乎正在“倾听”粒度参数。
现在修复我在使用'Minute'粒度时发现的错误 - 谢谢大家!