2015-03-24 75 views
1

下面的方法調用失敗,並顯示消息「將varchar數據類型轉換爲日期時間數據類型導致超出範圍值「。:當查詢結果有超過1000條記錄時,由Dapper拋出的System.Data.SqlClient.SqlException

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版)中執行查詢時,我也不會收到錯誤。即使我從選擇中刪除TOP並在SSMS中執行它,也不會發生錯誤(如預期的那樣返回了12,000多條記錄)。

我應該做些什麼而不是上面的實現來成功檢索超過1000行的結果集?在這種情況下,存儲過程會更合適嗎?

+1

BeginDate和EndDate的數據類型是什麼?它包含什麼格式的數據?也沒有一個訂單,不保證你會得到2000行。 – 2015-03-24 21:49:43

+0

我嚴重懷疑這與Dapper有什麼關係。這個例外是完全無關的。 – mxmissile 2015-03-24 21:51:59

+0

我已經更新了我的問題,以反映我已經在SQL Server Management Studio中嘗試過所有這些查詢的變體,並且所有工作都正常。 BeginDate和EndDate(不幸的是我)varchar(8)。我會嘗試添加一個ORDER BY子句來查看/如何改變我的結果。 – 2015-03-25 11:11:21

回答

2

聲音就像你的日期字段存儲在一個varchar列中。 理想情況下,您應該將它們更改爲datetime字段。 如果這不是一個選擇,改變你的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條記錄都包含有效日期。

+0

我會嘗試根據您的建議更改WHERE子句並查看是否可以解決錯誤。 – 2015-03-25 11:15:40

+0

非常感謝您的幫助。當我將WHERE子句更新爲您所建議的內容時,沒有更多的錯誤。我仍然不確定爲什麼SSMS沒有給我以前的查詢錯誤,但你的建議已經解決了我的問題。 – 2015-03-25 14:44:57

1

這是一個數據庫服務器錯誤:dapper不知道varchar並且沒有考慮varchar - 它談到.net String s。所以:你的日期之一 - stored-as-varchar被破壞並且不包含有效值。

基本上:在SSMS中試試這個查詢:我預計它也會在那裏出現!

更改爲存儲過程根本不會改變這一點。需要改變的是破壞的數據 - (更重要的是)在基於文本的列中存儲日期/時間數據的不好選擇。

+0

不幸的是,數據類型選擇不是我的。我在SSMS中測試了這個查詢,並在將它添加到我的代碼之前沒有發現錯誤。 – 2015-03-25 11:14:50

+0

@ ScottA.Lawrence,你是否對* actual *數據進行了測試?或者僅僅針對您的本地/開發數據? – 2015-03-25 11:17:14

+0

根據實際數據進行了測試(我們的臨時環境中的數據是從我們的生產環境更新的)。 – 2015-03-25 14:37:00

相關問題