Dapper And System.Data.OleDb DbType.Date lance 'OleDbException: incompatibilité de type de données dans l'expression de critères'

dapper ms-access oledbconnection

Question

Je ne suis pas sûr que je devrais soulever un problème à ce sujet, alors j'ai pensé que je demanderais si quelqu'un connaissait une solution de contournement simple pour cela en premier. Je reçois une erreur lorsque j'essaie d'utiliser Dapper avec OleDbConnection lorsqu'il est utilisé avec MS Access 2003 (Jet.4.0) (pas mon choix de base de données!)

Lors de l'exécution du code de test ci-dessous, je reçois une exception "OleDbException: incompatibilité de type de données dans l'expression de critères"

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

Je crois par expérience avec les dates OleDb que lors de la définition de DbType à Date, il change ensuite en interne la valeur de la propriété OleDbType en OleDbTimeStamp au lieu de OleDbType.Date. Je comprends que ce n'est pas à cause de Dapper, mais ce qui pourrait être considéré comme une façon étrange de relier en interne dans la classe OleDbParameter

En traitant ceci soit en utilisant d'autres ORM, ADO brut ou mes propres objets de fabrique, je nettoierais l'objet de commande juste avant d'exécuter la commande et changerais OleDbType à Date.

Cela n'est pas possible avec Dapper, pour autant que je puisse le voir, car l'objet de commande semble être interne. Malheureusement, je n'ai pas eu le temps d'apprendre les techniques de génération dynamique, de sorte que je pourrais rater quelque chose de simple ou suggérer une solution et contribuer plutôt que de simplement soulever un problème.

Des pensées?

Lee

Réponse acceptée

C'est un ancien thread mais j'ai le même problème: Access n'aime pas DateTime avec des millisecondes, vous devez donc ajouter et étendre la méthode comme ceci:

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

Et l'utiliser lors du passage de paramètres:

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

Malheureusement, avec la version actuelle de Dapper (1.42), nous ne pouvons pas ajouter TypeHandler personnalisé pour les types de base (voir # 206 ).

Si vous pouvez modifier Dapper (utilisez le fichier cs et non la DLL), fusionnez cette requête pull et vous n’aurez plus à utiliser Floor sur chaque paramètre:

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



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