Dapper y System.Data.OleDb DbType.Date lanzando 'OleDbException: tipo de datos no coinciden en la expresión de criterios'

dapper ms-access oledbconnection

Pregunta

No estoy seguro si debería plantear un problema con respecto a esto, así que pensé en preguntar si alguien conocía una solución simple para esto primero. Me aparece un error cuando trato de utilizar Dapper con OleDbConnection cuando se usa en combinación con MS Access 2003 (Jet.4.0) (¡no es mi elección de base de datos!)

Cuando ejecuto el código de prueba a continuación, obtengo una excepción 'OleDbException: desajuste del tipo de datos en la expresión de criterios'

var count = 0;

using (var conn = new OleDbConnection(connString)) {

    conn.Open();
    var qry = conn.Query<TestTable>("select * from testtable where CreatedOn <= @CreatedOn;", new { CreatedOn = DateTime.Now });
    count = qry.Count();
}

Creo que por experiencia en el pasado con las fechas de OleDb, es que al establecer el Tipo de Db en Fecha, entonces cambia internamente el valor de la propiedad OleDbType a OleDbTimeStamp en lugar de OleDbType.Date. Entiendo que esto no se debe a Dapper, sino a lo que 'podría' considerarse una forma extraña de vincularse internamente en la clase OleDbParameter

Al tratar con esto, ya sea usando otros ORM, ADO sin procesar o mis propios objetos de fábrica, limpiaría el objeto de comando justo antes de ejecutar el comando y cambiaría OleDbType a Date.

Esto no es posible con Dapper por lo que puedo ver, ya que el objeto de comando parece ser interno. Lamentablemente, no he tenido tiempo de aprender sobre la generación dinámica, por lo que me podría estar perdiendo algo simple o podría sugerir una solución y contribuir en lugar de simplemente plantear un problema.

¿Alguna idea?

Sotavento

Respuesta aceptada

Es un hilo viejo pero tuve el mismo problema: Access no le gusta DateTime con milisegundos, por lo que debe agregar un método de extensión como este:

public static DateTime Floor(this DateTime date, TimeSpan span)
{
    long ticks = date.Ticks / span.Ticks;
    return new DateTime(ticks * span.Ticks, date.Kind);
}

Y úsala al pasar los parámetros:

var qry = conn.Query<TestTable>("select * from testtable where CreatedOn <= @CreatedOn;", new { CreatedOn = DateTime.Now.Floor(TimeSpan.FromSeconds(1)) });

Desafortunadamente, con la versión actual de Dapper (1.42), no podemos agregar TypeHandler personalizado para los tipos base (ver # 206 ).

Si puede modificar Dapper (use el archivo cs y no el DLL) fusione esta solicitud de extracción y luego no tenga que usar Floor en cada parámetro:

public class DateTimeTypeHandler : SqlMapper.TypeHandler<DateTime>
{
    public override DateTime Parse(object value)
    {
        if (value == null || value is DBNull) 
        { 
            return default(DateTime); 
        }
        return (DateTime)value;
    }

    public override void SetValue(IDbDataParameter parameter, DateTime value)
    {
        parameter.DbType = DbType.DateTime;
        parameter.Value = value.Floor(TimeSpan.FromSeconds(1));
    }
}

SqlMapper.AddTypeHandler<DateTime>(new DateTimeTypeHandler());


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow