c# - example - Dapper tipos de retorno dinámico
remarks c# (3)
He estado usando dapper.net por ahora y es un muy buen mapeador ORM que funciona muy bien con los tipos dinámicos .Net pero noté que cuando Dapper recupera datos de la base de datos, regresa como tipo de fila Dapper. en cualquier otro tipo, como System.Dynamic.ExpandoObject?
¡Por supuesto!
Según la documentación de Dapper, utilice el método de consulta y obtenga su dinámica:
dynamic account = conn.Query<dynamic>(@"
SELECT Name, Address, Country
FROM Account
WHERE Id = @Id", new { Id = Id }).FirstOrDefault();
Console.WriteLine(account.Name);
Console.WriteLine(account.Address);
Console.WriteLine(account.Country);
Como puede ver, obtiene un objeto dinámico y puede acceder a sus propiedades siempre que estén bien definidas en la declaración de consulta.
Si omite .FirstOrDefault()
, obtiene un IEnumerable<dynamic>
que puede hacer lo que quiera con él.
Tengo este problema y lo solucioné de esta manera!
La función Query()
devuelve una colección de dinámicas que debajo son en realidad tipos de objetos Dapper.SqlMapper.DapperRow
. El Dapper.SqlMapper.DapperRow
es privado. Necesitaba agregar propiedades dinámicamente a los objetos Dapper.SqlMapper.DapperRow pero eso no parece funcionar. Como resultado, quería convertir el Dapper.SqlMapper.DapperRow
en un ExpandoObject
.
Pude construir este método genérico de ayuda como se muestra a continuación.
public class DapperHelpers
{
public static dynamic ToExpandoObject(object value)
{
IDictionary<string, object> dapperRowProperties = value as IDictionary<string, object>;
IDictionary<string, object> expando = new ExpandoObject();
foreach (KeyValuePair<string, object> property in dapperRowProperties)
expando.Add(property.Key, property.Value);
return expando as ExpandoObject;
}
}
Entonces puedes usar eso así:
IEnumerable<ExpandoObject> result =
db.SqlConn.Query(sqlScript)
.Select(x=> (ExpandoObject)ToExpandoObject(x));
referencia: cuestiones dapper-punto-net 166
El objeto DapperRow
está diseñado para compartir muchos estados entre filas. Por ejemplo, si obtiene 40 filas, los nombres de columna, etc., solo se almacenan una vez . Si utilizamos ExpandoObject
, esto debería configurarse por fila. Por lo tanto, el uso de DapperRow
como el detalle de implementación detrás de escena es una cuestión de eficiencia deliberada.
Tenga en cuenta que el objeto devuelto desde las API dynamic
también se puede convertir como IDictionary<string,object>
.
Sin embargo, estaría abierto a admitir otros tipos que admitan este uso del diccionario, de los cuales ExpandoObject
es uno. Entonces sí, podría ser cambiado de tal manera que:
var rows = conn.Query<ExpandoObject>(...);
trabajos. Simplemente requiere código para soportarlo , y ese código no existe actualmente. Así que "no, pero tal vez en una futura compilación".
Tenga en cuenta también que no necesita usar DapperRow
en absoluto ... El escenario más esperado es utilizar la API genérica para materializar sus propios tipos.