Dapper 和 System.Data.OleDb DbType.Date 抛出“OleDbException:条件表达式中的数据类型不匹配”

Lsk*_*ski 4 ms-access oledbconnection dapper

不确定我是否应该提出有关此问题的问题,所以我想先问问是否有人知道一个简单的解决方法。当我尝试将 Dapper 与 OleDbConnection 与 MS Access 2003 (Jet.4.0)(不是我选择的数据库!)结合使用时,出现错误

运行下面的测试代码时,出现异常“OleDbException:条件表达式中的数据类型不匹配”

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();
}
Run Code Online (Sandbox Code Playgroud)

我相信根据过去使用 OleDb 日期的经验,当将 DbType 设置为 Date 时,它​​会在内部将 OleDbType 属性的值更改为 OleDbTimeStamp 而不是 OleDbType.Date。我知道这不是因为 Dapper,而是在 OleDbParameter 类中“可能”被认为是一种奇怪的内部链接方式

当使用其他 ORM、原始 ADO 或我自己的工厂对象处理此问题时,我会在运行命令之前清理命令对象并将 OleDbType 更改为 Date。

据我所知,这对于 Dapper 来说是不可能的,因为命令对象似乎是内部的。不幸的是,我没有时间学习动态生成的东西,所以我可能会错过一些简单的东西,或者我可能会建议修复并做出贡献,而不是简单地提出问题。

有什么想法吗?

Pla*_*Man 5

这是一个旧线程,但我遇到了同样的问题:Access 不喜欢带有毫秒的 DateTime,因此您必须添加和扩展方法,如下所示:

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

并在传递参数时使用它:

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

不幸的是,在当前的 Dapper 版本 (1.42) 中,我们无法为基本类型添加自定义 TypeHandler (参见#206 )。

如果您可以修改 Dapper(使用 cs 文件而不是 DLL)合并此拉取请求,那么您不必Floor在每个参数上使用:

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());
Run Code Online (Sandbox Code Playgroud)