2016-06-24 35 views
0

SQL Serverデータベースからレポートを生成するC#コンソールアプリケーションがあります。すべてのレポートはストアドプロシージャに基づいており、私のアプリケーションコードはストアドプロシージャをすべて同じ方法で呼び出します。構造化されたSQL文字列と同じ結果を返さないストアドプロシージャ

SQL Server Management Studioから実行したときにストアドプロシージャが正常に機能したにもかかわらず、ストアドプロシージャが期待どおりに機能しないという問題が発生しました。

私はこの問題を解決しようとしています。できるだけ多くの異なる方法で解剖しました。もう少し余分な目でこのコードを調べても、これを動作させることはできません。サーバー上の

// code in my app 
public DataTable DeviceAuthorizationAffectedDeviceGroup(string affectedDeviceGroupNameArray, DateTime startDate, int deviceId) { 
    dt = new DataTable(); 
    DataTable dt2 = new DataTable(); 

    string sql = "SELECT StartTime EventTime, EventText, UserName AS Username, AffectedDeviceGroupName"; 
    sql += " FROM eventlog"; 
    sql += " WHERE AffectedDeviceGroupName IN (SELECT LTRIM(RTRIM(Item)) FROM dbo.SplitString('" + affectedDeviceGroupNameArray + "', ','))"; 
    sql += " AND StartTime >= '" + startDate + "'"; 
    sql += " AND (DeviceID = " + deviceId + ")"; 
    sql += " ORDER BY StartTime"; 

    using (var cn = new SqlConnection(this.ConnectionString)) { 
     using (var cmd = new SqlCommand(sql, cn)) { 
      using (var da = new SqlDataAdapter(cmd)) { 
       cmd.CommandType = CommandType.Text; 

       Debug.WriteLine(MyDamnClass.CommandAsSql(cmd)); 
       da.Fill(dt); //SQL string, data table contains 6 rows 
      } 
     } 

     using (var cmd = new SqlCommand("usp_REPORTS_SubReport_GetDeviceAuthorizationAffectedDeviceGroup_TEST", cn)) { 
      using (var da = new SqlDataAdapter(cmd)) { 
       cmd.CommandType = CommandType.StoredProcedure; 
       cmd.Parameters.Add("@AffectedDeviceGroupNameArray", SqlDbType.VarChar).Value = affectedDeviceGroupNameArray; 
       cmd.Parameters.Add("@StartTime", SqlDbType.DateTime).Value = startDate; 
       cmd.Parameters.Add("@DeviceID", SqlDbType.Int).Value = deviceId; 

       Debug.WriteLine(MyDamnClass.CommandAsSql(cmd)); 
       da.Fill(dt2); //stored proc, data table contains 0 rows 
      } 
     } 
    } 

    return dt; 
} // breakpoint here to examine the contents of each data table 

ストアド手順:(this questionからフラッパーのコード@使用して)私のアプリから実行されて

CREATE PROCEDURE [dbo].[usp_REPORTS_SubReport_GetDeviceAuthorizationAffectedDeviceGroup_TEST] 
    (@AffectedDeviceGroupNameArray varchar(MAX), 
     @StartTime datetime, @DeviceID int) 
AS 
    SELECT 
     StartTime EventTime, 
     EventText, 
     UserName AS Username, 
     AffectedDeviceGroupName 
    FROM 
     eventlog 
    WHERE 
     AffectedDeviceGroupName IN (SELECT LTRIM(RTRIM(Item)) 
            FROM dbo.SplitString(@AffectedDeviceGroupNameArray, ',')) 
     AND StartTime >= @StartTime 
     AND (DeviceID = @DeviceID) 
    ORDER BY 
     StartTime 

SQLコード

use MyDatabase; 
SELECT 
    StartTime EventTime, EventText, UserName AS Username, 
    AffectedDeviceGroupName 
FROM 
    eventlog 
WHERE 
    AffectedDeviceGroupName IN (SELECT LTRIM(RTRIM(Item)) 
           FROM dbo.SplitString('(Unassigned)', ',')) 
    AND StartTime >= '10/12/2015 2:46:51 PM' 
    AND (DeviceID = 281) 
ORDER BY 
    StartTime 

use MyDatabase; 
declare @return_value int; 
exec [usp_REPORTS_SubReport_GetDeviceAuthorizationAffectedDeviceGroup_TEST] 
    @AffectedDeviceGroupNameArray = '(Unassigned)' 
    , @StartTime = '10/12/2015 2:46:51 PM' 
    , @DeviceID = 281 
; 
select 'Return Value' = convert(varchar, @return_value); 

私は何を見ていないのですか?同一の構築されたSQL文字列が私が期待しているものを返すときにストアドプロシージャが行を返さない原因は何ですか?私はそれが何か小さなものだと確信しており、それらのうちの1つを引き起こします "ああ!一度それが指摘されている瞬間。

+1

をあなたは本当に、パラメータ化クエリを使用する必要があります。文字列の接触が信頼できない場合は、パラメータを使用するようにテキストバージョンを切り替えて、それが修正されているかどうかを確認してください。 –

+3

あなたのC#コードでDateTimeが(連結のために)文字列に強制されているのに対し、ストアドプロシージャを呼び出すときにDateTimeとして(パラメータを介して)渡されているのでしょうか。 – Duston

+0

また、 'yyyy-mm-ddThh:mi:ss'という文字列リテラルの書式であり、他の書式は言語/設定に固有です。それがここの理由かどうかは分かりません。 –

答えて

1

文字列を連結して作成したselect文とストアドプロシージャの実行の違いの1つは、比較するパラメータのデータ型です。テーブルフィールドのデータ型に応じて、メソッド間の結果が変更される可能性があります。特に、eventlogテーブルのStartTimeフィールドがdatetimeではなくvarcharである場合、異なる結果が得られます。あなたは文字列リテラルにのStartTimeフィールドを比較しているあなたの選択クエリで

StartTime >= '" + startDate + "'"; 

StartTimeは、varchar型のタイプである場合、これは代わりではありません日付の比較、の文字列比較につながりますあなたが意図したもの。それはアルファベット順に日付をソートするので、たとえば'10/12/2015 2:46:51 PM 'は'01/12/2016 2:46:51 PM'より大きくなります。これは1で始まり、もう1つは0

しかし、StartTimeフィールドをストアドプロシージャのパラメータと比較すると、datetimeとデータが比較されます。データ型の優先順位のために、テーブルフィールドをdatetimeデータ型に暗黙的に変換し、その2つを日付として比較しようとします。

あなたがのStartTimeフィールドまたは文字列パラメータのいずれかの日時を明示的に変換を行う場合は、両方の方法で同じ結果を得る必要があります。

convert(datetime, StartTime) >= '" + startDate + "'"; 
関連する問題