쿼리 결과에 1000 개가 넘는 레코드가있는 경우 Dapper에 의해 throw되는 System.Data.SqlClient.SqlException

c# dapper dapper-extensions sql sql-server

문제

아래의 메서드 호출은 "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 판)에서 쿼리를 실행해도 오류가 발생하지 않습니다. select에서 TOP을 제거하고 SSMS에서 실행하더라도 아무런 오류도 발생하지 않습니다 (예상대로 12,000 개 이상의 레코드가 반환됩니다).

위의 구현 대신 1000 행 이상의 결과 집합을 성공적으로 검색하려면 무엇을해야합니까? 이 경우 저장 프로 시저가 더 적절합니까?

수락 된 답변

날짜 필드와 같은 소리는 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 개 쿼리에서 성공한 이유 일 가능성이 큽니다.


전문가 답변

날씬한 VARCHAR에 대해 알고하지 않으며, VARCHAR의 측면에서 고려하지 않습니다 - 그것은 .NET에 대해 이야기 : 즉, 데이터베이스 서버 오류가 String 의. 그래서 : 날짜 중 하나 - stored-as-varchar가 손상되어 유효한 값을 포함하지 않습니다.

기본적으로 SSMS에서 다음 쿼리를 시도해보십시오.

저장 프로 시저로 변경해도 변경되지 않습니다. 변경해야 할 것은 깨진 데이터와 텍스트 기반 열에 날짜 / 시간 데이터를 저장하는 나쁜 선택입니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.