使用OleDb在Dapper中传递查询参数

End*_*ono 11 oledb dapper

此查询产生错误No value given for one or more required parameters:

using (var conn = new OleDbConnection("Provider=..."))
{
  conn.Open();
  var result = conn.Query(
    "select code, name from mytable where id = ? order by name",
    new { id = 1 });
}
Run Code Online (Sandbox Code Playgroud)

如果我将查询字符串更改为:... where id = @id ...,我将收到错误:Must declare the scalar variable "@id".

如何构造查询字符串以及如何传递参数?

Mar*_*ell 12

当前的源代码(尚未发布到NuGet)解决了这个问题; 以下应该有效:

var result = conn.Query(
"select code, name from mytable where id = ?id? order by name",
new { id = 1 });
Run Code Online (Sandbox Code Playgroud)

  • 为什么不@dd为oledb? (3认同)

Mar*_*ell 7

重要提示:请参阅更新的答案


在当前版本中,答案就是"不",原因有两个:

  • 代码尝试过滤未使用的参数 - 并且当前正在删除它们,因为它找不到任何类似的东西@id,:id或者?id在sql中
  • 从类型中添加值的代码对参数使用任意(well,ok:alphabetical)顺序(因为反射不会对成员的顺序做出任何保证),使得位置匿名参数不稳定

好消息是这两个都是可以解决的

  • 我们可以使过滤行为成为条件
  • 我们可以检测具有与所有属性名称匹配的构造函数的类型类别,并使用构造函数参数位置来确定属性的合成顺序 - 匿名类型属于此类别

将这些更改发布到我的本地克隆,现在传递以下内容:

// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
    using (var conn = new System.Data.OleDb.OleDbConnection(
        Program.OleDbConnectionString))
    {
        var row = conn.Query("select Id = ?, Age = ?", new DynamicParameters(
            new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
        ) { RemoveUnused = false } ).Single();
        int age = row.Age;
        int id = row.Id;
        age.IsEqualTo(23);
        id.IsEqualTo(12);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我目前正在使用DynamicParameters此处以避免向Query/ 添加更多重载,Query<T>因为这需要添加到相当多的方法中.添加它以DynamicParameters在一个地方解决它.

在我推动之前,我愿意接受反馈 - 这看起来对您有用吗?


编辑:添加一个时髦smellsLikeOleDb(不,不是笑话),我们现在可以更直接地做到这一点:

// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
    using (var conn = new System.Data.OleDb.OleDbConnection(
        Program.OleDbConnectionString))
    {
        var row = conn.Query("select Id = ?, Age = ?",
            new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
        ).Single();
        int age = row.Age;
        int id = row.Id;
        age.IsEqualTo(23);
        id.IsEqualTo(12);
    }
}
Run Code Online (Sandbox Code Playgroud)