Pasar parámetros de consulta en Dapper usando OleDb

dapper oledb

Pregunta

Esta consulta produce un error. 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 });
}

Si cambio la cadena de consulta a: ... where id = @id ... , obtendré un error: Must declare the scalar variable "@id".

¿Cómo construyo la cadena de consulta y cómo paso el parámetro?

Respuesta aceptada

El código fuente actual (aún no lanzado a NuGet) resuelve este problema; lo siguiente debería funcionar:

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

Respuesta experta

Importante: vea una respuesta más nueva


En la compilación actual, la respuesta sería "no", por dos razones:

  • el código intenta filtrar parámetros no utilizados, y actualmente los está eliminando porque no puede encontrar nada como @id :id o ?id en el sql
  • el código para agregar valores de tipos usa un orden arbitrario (bien, ok: alfabético) para los parámetros (porque la reflexión no garantiza el orden de los miembros), lo que hace que los argumentos posicionales anónimos sean inestables

La buena noticia es que ambos son corregibles

  • podemos hacer que el comportamiento de filtrado sea condicional
  • podemos detectar la categoría de tipos que tiene un constructor que coincide con todos los nombres de propiedad, y usar las posiciones del argumento del constructor para determinar el orden sintético de las propiedades: los tipos anónimos entran en esta categoría

Al hacer esos cambios a mi clon local, ahora pasa lo siguiente:

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

Tenga en cuenta que actualmente estoy usando DynamicParameters aquí para evitar agregar aún más sobrecargas a Query / Query<T> , ya que esto debería agregarse a una cantidad considerable de métodos. Agregarlo a DynamicParameters resuelve en un solo lugar.

Estoy abierto a comentarios antes de presionar esto, ¿te parece útil?


Editar: con la adición de un funky smellsLikeOleDb (no, no es una broma), ahora podemos hacer esto aún más directamente:

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


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow