【问题标题】:System.Data.SqlClient.SqlException Thrown by Dapper When Query Result Has More Than 1000 Records查询结果超过 1000 条记录时 Dapper 抛出 System.Data.SqlClient.SqlException
【发布时间】:2015-03-25 19:08:10
【问题描述】:

以下方法调用失败,并显示消息“将 varchar 数据类型转换为日期时间数据类型导致值超出范围。”:

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 行的结果集?在这种情况下,存储过程会更合适吗?

【问题讨论】:

  • BeginDate 和 EndDate 的数据类型是什么?它包含什么格式的数据?此外,如果没有订单,也无法保证您将获得 2,000 行。
  • 我严重怀疑这与 Dapper 有任何关系。该异常完全不相关。
  • 我已经更新了我的问题,以反映我已经在 SQL Server Management Studio 中尝试了此查询的变体,这些变体都可以正常工作。 BeginDate 和 EndDate 是(不幸的是我)varchar(8)。我会尝试添加一个 ORDER BY 子句,看看是否/如何改变我的结果。

标签: c# sql sql-server dapper dapper-extensions


【解决方案1】:

听起来您的日期字段存储在 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 条记录都包含有效日期。

【讨论】:

  • 我将尝试按照您的建议更改 WHERE 子句,看看是否可以解决错误。
  • 非常感谢您的帮助。当我将 WHERE 子句更新为您建议的内容时,不再出现错误。我仍然不确定为什么 SSMS 在之前的查询中没有给我一个错误,但你的建议已经解决了我的问题。
【解决方案2】:

这是一个数据库服务器错误:dapper 不知道 varchar 并且不接受 varchar - 它谈论的是 .net Strings。所以:您的日期存储为 varchar 之一已损坏且不包含有效值。

基本上:在 SSMS 中尝试这个查询:我希望它也会在那里中断!

更改为存储过程根本不会改变这一点。需要改变的是损坏的数据 - 以及(更重要的是)将日期/时间数据存储在基于文本的列中的错误选择。

【讨论】:

  • 不幸的是,数据类型的选择不是我的选择。我在 SSMS 中测试了查询,在将其添加到我的代码之前没有出错。
  • @ScottA.Lawrence,您是否针对 实际 数据进行了测试?还是仅仅针对您的本地/开发数据?
  • 针对实际数据(暂存环境中从生产环境更新的数据)进行测试。
猜你喜欢
  • 2012-05-04
  • 2014-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-22
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多