System.Data.SqlClient.SqlException générée par Dapper lorsque le résultat d'une requête contient plus de 1 000 enregistrements

c# dapper dapper-extensions sql sql-server

Question

L'appel de méthode ci-dessous échoue avec le message "La conversion d'un type de données varchar en un type de données datetime a abouti à une valeur hors plage.":

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 le jeu de résultats contient 1000 enregistrements (ou moins), le code fonctionne correctement. Lorsque j'exécute la requête dans SQL Server Management Studio (édition 2014), je ne reçois pas non plus d'erreur. Même lorsque je supprime le TOP de la sélection et l'exécute dans SSMS, aucune erreur ne se produit (plus de 12 000 enregistrements sont renvoyés, comme prévu).

Que dois-je faire à la place de l'implémentation ci-dessus pour récupérer avec succès des jeux de résultats contenant plus de 1000 lignes? Une procédure stockée serait-elle plus appropriée dans ce cas?

Réponse acceptée

On dirait que vos champs de date sont stockés dans une colonne varchar. Idéalement, vous devriez les remplacer par des champs datetime. Si ce n'est pas une option, modifiez votre clause WHERE pour qu'elle ressemble à ceci:

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 raison pour laquelle elle a réussi sur votre requête principale est probablement parce que les 1000 premiers enregistrements trouvés contenaient tous des dates valides.


Réponse d'expert

C'est une erreur du serveur de base de données: dapper ne connaît pas varchar et ne prend pas en compte varchar - il parle des String .net. Donc, l'un de vos dates-stock-as-varchar est cassé et ne contient pas de valeur valide.

Fondamentalement: essayez cette requête dans SSMS: je pense que ça va casser là aussi!

Passer à une procédure stockée ne changera rien à cela. Ce qui doit changer, ce sont les données brisées - et (plus important) le mauvais choix de stockage des données de date / heure dans une colonne textuelle.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi