0

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
...

(暂时忽略 avg,这无关紧要)。

当我直接从 SQL 以这种方式调用它时,我已经验证该函数正在工作。

我正在使用这个存储过程来绘制使用实体框架插件(EF 版本 4.0.0.0)的 MVC 应用程序中的一些数据。首先,我使用数据库中的更改更新了 .edmx 文件。我打开模型资源管理器并为 GetResultsByTime 添加了一个函数导入,使用向导自动生成一个新的复杂类型 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

当我使用服务器资源管理器执行存储过程时,我再次得到正确的结果:

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

现在它似乎在“倾听”粒度论点。

现在修复我在使用“分钟”粒度时发现的错误 - 谢谢大家!

4

0 回答 0