Consultas parametrizadas Dapper con tipos autogenerados LINQ

c# dapper linq

Pregunta

Estoy usando una combinación de LINQ y Dapper en mi trabajo. Estoy reemplazando mi código LINQ con Dapper en lugares por razones de rendimiento. Tengo muchos objetos de datos LINQ creados al arrastrar y soltar en el diagrama de la base de datos de Visual Studio desde SQL Server.

En la siguiente instancia, ya tengo un objeto LINQ en la memoria y me gustaría pasarlo a Dapper como los parámetros para una consulta. Por ejemplo:

Animal animal = con.Query<Animal>(" select * " +
        " from animal " +
        " where animalid = @AnimalId " +
        " and animaltype = @AnimalType ",
        cagedAnimal).SingleOrDefault();

cagedAnimal contiene propiedades públicas AnimalId y AnimalType con getters y setters.

Sin embargo, al ejecutar este código, aparece el siguiente error:

El tipo: SMDApp.Models.Animal no es compatible con dapper

El siguiente código funciona:

Animal animal = con.Query<Animal>(" select * " +
            " from animal " +
            " where animalid = @AnimalId " +
            " and animaltype = @AnimalType ",
            new 
            { 
            AnimalId = cagedAnimal.AnimalId, 
            AnimalType = cagedAnimal.AnimalType 
            }
            ).SingleOrDefault();

Sería más conveniente para mí usar un objeto existente, particularmente cuando estoy usando más de una propiedad del objeto como parámetro para la consulta. ¿Alguien puede decirme por qué esto funciona para un objeto anónimo pero no un objeto LINQ generado automáticamente?

Editado en respuesta a la respuesta de Ben Robinson.

Editado por segunda vez en respuesta a la respuesta de Marc Gravell.

Respuesta aceptada

La versión corta es que ya debería funcionar ; basado en el error:

El tipo: SMDApp.Models.CagedAnimal no es compatible con dapper

Concluyo que o bien está pasando un new {cagedAnimal} lugar de un cagedAnimal , o , su CagedAnimal tiene una propiedad (¿ Parent , quizás?) Que es a su vez un CagedAnimal , y que apuesto no puede entender. El comportamiento actual es que se agrega un parámetro para cada propiedad pública del objeto de parámetro proporcionado, y si no puede averiguar cómo enviar cualquiera de las propiedades a la base de datos, se queja. Debería encontrar que un POCO simple con miembros de valor justo funciona bien.

¡Sin embargo! Tenga en cuenta que nunca intenta analizar su SQL, en particular, no verifica los parámetros en la consulta proporcionada. Como tal, usar el enfoque POCO significará que está agregando propiedades innecesarias a la consulta.

Usamos dapper extensivamente, y solo usamos el enfoque:

 new { obj.Foo, obj.Bar, id, key = "something else" }

Respuesta popular

Marc acaba de realizar un cambio para solucionar este problema en particular:

  1. Realizamos una validación trivial antes de enviar intentos de traducir propiedades a params. Por ejemplo, Dapper no enviará ningún parámetro al servidor para este caso: cnn.Query ("select 1", new {bla = 1}) porque "bla" no existe en la cadena. Esta validación se omite para los procesos almacenados.

  2. El error, que era bastante críptico, ahora está arreglado y mejorado mucho.

-

Dapper solía realizar un análisis sintáctico de la instrucción SQL subyacente, por lo que, por ejemplo:

@"select * 
from animal
where animalid = @AnimalId"

Contiene un solo @AnimalId llamado @AnimalId .

Se complica porque, para ser 100% correcto, necesitas manejar casos @AnimalId EG: @AnimalId en la cadena select '@AnimalId' -- @AnimalId \* @AnimalId *\ ? La expresión regular se vuelve un poco complicada, no he pensado en todos los casos extremos. Por ejemplo: Oracle prefije sus params con a : que complica más las cosas.

Como Dapper no sabía nada sobre los params en la cadena, decidió enviar todas las propiedades públicas como un parámetro. Algunas de sus propiedades públicas no se pueden asignar a DbParameters por lo que se quejó.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué