System.Data.SqlClient.SqlException generata da Dapper quando il risultato della query ha più di 1000 record

c# dapper dapper-extensions sql sql-server

Domanda

La seguente chiamata al metodo ha esito negativo con il messaggio "La conversione di un tipo di dati varchar in un tipo di dati datetime ha prodotto un valore fuori intervallo.":

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

Se il set di risultati contiene 1000 (o meno) record, il codice funziona correttamente. Quando eseguo la query in SQL Server Management Studio (edizione 2014), non ottengo neanche un errore. Anche quando rimuovo il TOP dalla selezione e lo eseguo in SSMS, non si verifica alcun errore (12.000 record vengono restituiti, come previsto).

Cosa dovrei fare invece dell'implementazione di cui sopra per recuperare con successo set di risultati con più di 1000 righe? In questo caso, una stored procedure sarebbe più appropriata?

Risposta accettata

Sembra che i tuoi campi data siano memorizzati in una colonna varchar. Idealmente, dovresti cambiarli in campi datetime. Se non è un'opzione, modifica la clausola WHERE in modo che assomigli a questa:

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 ragione per cui è riuscita nella tua top 1000 query è probabilmente perché i primi 1000 record trovati hanno contenuto date valide.


Risposta esperta

Questo è un errore del server database: dapper non sa su varchar e non prende in termini di varchar - parla di .net String s. Quindi: una delle tue date-stored-as-varchar è rotta e non contiene un valore valido.

Fondamentalmente: prova questa query in SSMS: mi aspetto che si interrompa anche lì!

Passare a una stored procedure non lo cambierà affatto. Ciò che deve cambiare sono i dati non funzionanti e (cosa più importante) la cattiva scelta di memorizzare dati di data / ora in una colonna di testo.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché