1

以下のメソッド呼び出しは、「varchar データ型から datetime データ型への変換により、範囲外の値が発生しました。」というメッセージが表示されて失敗します。

public IEnumerable<SomeResult> GetResults(SqlConnection connection, string attribute)
    {
        var sql = string.Format(@"
        SELECT TOP 2000
            r.Id
            ,r.LastName
            ,r.FirstName
            ,r.Ssn
            ,r.CurrentId
            ,BeginDate = case when isdate(rli.BeginDate) = 1 then convert(datetime, rli.BeginDate) else NULL end
            ,EndDate = case when isdate(rli.EndDate) = 1 then convert(datetime, rli.EndDate) else NULL end
            ,rli.LcknTyCd
            ,rli.ProvId
        FROM 
            [dbo].[Span] rli
            INNER JOIN [dbo].Recipient r
                ON rli.SysId = r.SysId
            INNER JOIN [dbo].ValidRecipient lc
                ON r.SysId = lc.SysId
        WHERE 
            BeginDate <= GETDATE()
            AND EndDate >= GETDATE()
            AND rli.LcknTyCd = @LcknTyCd);

        return connection.Query<SomeResult>(sql, new { LcknTyCd = attribute}).ToList();
    }

public struct SomeResult
{
    public string Id{ get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Ssn { get; set; }
    public string CurrentId{ get; set; }
    public DateTime? BeginDate { get; set; }
    public DateTime? EndDate { get; set; }
    public string LcknTyCd{ get; set; }
    public string ProvId{ get; set; }
}

結果セットに含まれるレコードが 1000 (またはそれ以下) の場合、コードは正しく機能します。SQL Server Management Studio (2014 edition) でクエリを実行しても、エラーは発生しません。選択から TOP を削除して SSMS で実行しても、エラーは発生しません (予想どおり、12,000 件以上のレコードが返されます)。

1000 行を超える結果セットを正常に取得するには、上記の実装の代わりに何をすべきですか? この場合、ストアド プロシージャの方が適切でしょうか?

4

2 に答える 2

2

これはデータベース サーバー エラーです。dapper は varchar を認識しておらず、varchar を考慮していません。.net について説明していますString。したがって、dates-stored-as-varchar の 1 つが壊れており、有効な値が含まれていません。

基本的に:SSMSでこのクエリを試してください:そこでも壊れると思います!

ストアド プロシージャに変更しても、これはまったく変更されません。変更する必要があるのは壊れたデータです。そして (さらに重要なことに) 日付/時刻データをテキストベースの列に格納するという不適切な選択です。

于 2015-03-24T22:13:57.797 に答える
2

日付フィールドが varchar 列に格納されているようです。理想的には、それらを日時フィールドに変更する必要があります。WHEREそれができない場合は、句を次のように変更します。

WHERE 
  case when isdate(rli.BeginDate) = 1 then convert(datetime, rli.BeginDate) else NULL end <= GETDATE()
  AND case when isdate(rli.EndDate) = 1 then convert(datetime, rli.EndDate) else NULL end >= GETDATE()
  AND rli.LcknTyCd = @LcknTyCd);

上位 1000 件のクエリで成功した理由は、上位 1000 件のレコードにすべて有効な日付が含まれていることが判明したためと考えられます。

于 2015-03-24T21:48:43.733 に答える