System.Data.SqlClient.SqlException Lanzado por Dapper cuando el resultado de la consulta tiene más de 1000 registros

c# dapper dapper-extensions sql sql-server

Pregunta

La llamada a método siguiente falla con el mensaje "La conversión de un tipo de datos varchar a un tipo de datos datetime resultó en un valor fuera de rango":

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; }
}

Si el conjunto de resultados contiene 1000 (o menos) registros, el código funciona correctamente. Cuando ejecuto la consulta en SQL Server Management Studio (edición 2014), tampoco obtengo un error. Incluso cuando elimino el TOP de la selección y lo ejecuto en SSMS, no se produce ningún error (se devuelven más de 12,000 registros, como se esperaba).

¿Qué debería estar haciendo en lugar de la implementación anterior para recuperar con éxito conjuntos de resultados con más de 1000 filas? ¿Sería un procedimiento almacenado más apropiado en este caso?

Respuesta aceptada

Parece que los campos de su fecha están almacenados en una columna varchar. Idealmente, debe cambiar esos campos a datetime. Si esa no es una opción, cambie su cláusula WHERE para que se vea así:

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);

La razón por la que tuvo éxito en su consulta de 1000 principales es probable porque los 1000 registros principales encontrados contienen todas las fechas válidas.


Respuesta experta

Ese es un error del servidor de la base de datos: dapper no sabe acerca de varchar y no toma en términos de varchar - habla sobre .net String s. Entonces: una de sus fechas almacenadas como varchar está rota y no contiene un valor válido.

Básicamente: prueba esta consulta en SSMS: ¡espero que también se rompa allí!

Cambiar a un procedimiento almacenado no cambiará esto en absoluto. Lo que debe cambiar es la información fragmentada y (más importante) la mala elección de almacenar datos de fecha / hora en una columna basada en texto.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué