0

TL;DR-SQLストアドプロシージャの関数インポートが間違ったデータを返しています。ストアドプロシージャを呼び出す他のすべてのメソッドは、正しいデータを返します。

SQL Server2008R2サーバーに次の署名を持つストアドプロシージャがあります

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パラメーターが、結果をグループ化する方法(分、時間、日、月、または年)を決定することです。たとえば、日付(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ファイルを更新しました。モデルエクスプローラーを開き、ウィザードを使用してGetResultsByTimeの関数インポートを追加し、新しい複合型GetResultsByTime_Resultを自動的に生成しました。ただし、生成された関数を使用すると、指定したものではなく、粒度の「日」を渡したかのように結果が得られます。例えば、

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                                                                                                                                                                                                                                                                

誰かアイデアはありますか?ストアドプロシージャを定義するSELECTに@granularityを追加して、SQLで期待どおりの値を取得し、渡されたのと同じ値を常に返すようにしました。残りのデータは次のようになります。 3(日)で合格しましたが。

冗長性をお詫び申し上げます。重要な詳細を省略しないように注意したいと思います。

編集:マシューの提案で、私はStackExchangeMiniProfilerを含めることでプロファイリングをオンにしました。Webサイトからデータを要求した後、プロファイラーは生成された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'粒度を使用しているときに見つけたエラーを修正します-ありがとうございました!

4

0 に答える 0