Passing query parameters in Dapper using OleDb

The following should work:

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

Important: see newer answer


In the current build, the answer to that would be "no", for two reasons:

  • the code attempts to filter unused parameters - and is currently removing all of them because it can't find anything like @id, :id or ?id in the sql
  • the code for adding values from types uses an arbitrary (well, ok: alphabetical) order for the parameters (because reflection does not make any guarantees about the order of members), making positional anonymous arguments unstable

The good news is that both of these are fixable

  • we can make the filtering behaviour conditional
  • we can detect the category of types that has a constructor that matches all the property names, and use the constructor argument positions to determine the synthetic order of the properties - anonymous types fall into this category

Making those changes to my local clone, the following now passes:

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

Note that I'm currently using DynamicParameters here to avoid adding even more overloads to Query / Query<T> - because this would need to be added to a considerable number of methods. Adding it to DynamicParameters solves it in one place.

I'm open to feedback before I push this - does that look usable to you?


Edit: with the addition of a funky smellsLikeOleDb (no, not a joke), we can now do this even more directly:

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

Tags:

Oledb

Dapper