Visual Studio 2010函数导入存储过程返回错误数据,忽略参数

时间:2013-01-16 21:03:49

标签: sql visual-studio entity-framework stored-procedures

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'粒度时发现的错误 - 谢谢大家!

0 个答案:

没有答案