Passing query parameters in Dapper using OleDb

前端 未结 4 1176
逝去的感伤
逝去的感伤 2020-12-03 21:55

This query produces an error No value given for one or more required parameters:

using (var conn = new OleDbConnection(\"Provider=...\"))
{
  co         


        
4条回答
  •  有刺的猬
    2020-12-03 22:07

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

提交回复
热议问题