System.Data.SqlClient.SqlException查询结果超过1000条时Dapper抛出
System.Data.SqlClient.SqlException Thrown by Dapper When Query Result Has More Than 1000 Records
下面的方法调用失败并显示消息 "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.":
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 版)中执行查询时,我也没有收到错误。即使我从 select 中删除 TOP 并在 SSMS 中执行它,也不会发生错误(按预期返回 12,000 多条记录)。
除了上述实现之外,我应该怎么做才能成功检索超过 1000 行的结果集?在这种情况下存储过程会更合适吗?
听起来您的日期字段存储在 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 条记录都包含有效日期。
这是一个数据库服务器错误:dapper 不知道 varchar 并且不接受 varchar - 它谈论 .net String
s。因此:您的日期存储为 varchar 之一已损坏且不包含有效值。
基本上:在 SSMS 中尝试这个查询:我希望它也会在那里中断!
更改为存储过程根本不会改变这一点。需要更改的是损坏的数据 - 以及(更重要的)将 date/time 数据存储在基于文本的列中的错误选择。
下面的方法调用失败并显示消息 "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.":
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 版)中执行查询时,我也没有收到错误。即使我从 select 中删除 TOP 并在 SSMS 中执行它,也不会发生错误(按预期返回 12,000 多条记录)。
除了上述实现之外,我应该怎么做才能成功检索超过 1000 行的结果集?在这种情况下存储过程会更合适吗?
听起来您的日期字段存储在 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 条记录都包含有效日期。
这是一个数据库服务器错误:dapper 不知道 varchar 并且不接受 varchar - 它谈论 .net String
s。因此:您的日期存储为 varchar 之一已损坏且不包含有效值。
基本上:在 SSMS 中尝试这个查询:我希望它也会在那里中断!
更改为存储过程根本不会改变这一点。需要更改的是损坏的数据 - 以及(更重要的)将 date/time 数据存储在基于文本的列中的错误选择。