web-dev-qa-db-fra.com

Comment renvoyer la liste des types dynamiques <dynamique> avec Dapper ORM

J'utilise Dapper.net depuis un certain temps maintenant et c'est un très bon mappeur ORM qui fonctionne très bien avec les types dynamiques .Net.

Mais j'ai remarqué que lorsque Dapper récupère des données d'une base de données, il retourne en tant que type DapperRow.

Existe-t-il un moyen de le renvoyer dans un autre type Comme System.Dynamic.ExpandoObject?

31
Husni Jabir

L'objet DapperRow est conçu pour partager beaucoup d'état entre les lignes. Par exemple, si vous récupérez 40 lignes, les noms des colonnes, etc. ne sont stockés que ne fois. Si nous utilisions ExpandoObject, cela devrait être configuré par ligne. Par conséquent, l'utilisation de DapperRow comme détail d'implémentation en arrière-plan est une chose délibérément efficace.

Notez que l'objet renvoyé par les API dynamic peut également être converti en IDictionary<string,object>.

Je serais toutefois ouvert à la prise en charge d'autres types qui prennent en charge cette utilisation du dictionnaire - dont ExpandoObject en est un. Alors oui, cela pourrait être modifié de telle sorte que:

var rows = conn.Query<ExpandoObject>(...);

travaux. Il nécessite simplement du code pour le supporter , et ce code n'existe pas actuellement. Donc "non, mais peut-être dans une future version".

Notez également que vous n'avez pas du tout besoin d'utiliser DapperRow ... Le scénario le plus attendu consiste à utiliser l'API générique pour matérialiser vos propres types.

28
Marc Gravell

Sûr!

Selon la documentation de Dapper, utilisez la méthode de requête et obtenez votre dymanics:

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

Comme vous pouvez le voir, vous obtenez un objet dynamique et vous pouvez accéder à ses propriétés tant qu'elles sont bien définies dans l'instruction de requête.

Si vous omettez .FirstOrDefault() vous obtenez un IEnumerable<dynamic> Que vous pouvez faire avec ce que vous voulez.

42
e4rthdog

J'ai ce problème et j'ai résolu de cette façon!

La fonction Query() renvoie une collection de dynamiques qui sont en dessous Dapper.SqlMapper.DapperRow types d'objets. Le Dapper.SqlMapper.DapperRow est privé. J'avais besoin d'ajouter dynamiquement des propriétés aux objets Dapper.SqlMapper.DapperRow mais cela ne semble pas fonctionner. Par conséquent, je voulais convertir le Dapper.SqlMapper.DapperRow dans un ExpandoObject.

J'ai pu créer cette méthode d'assistance générique comme ci-dessous.

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

Ensuite, vous pouvez utiliser cela comme ceci:

IEnumerable<ExpandoObject> result = 
           db.SqlConn.Query(sqlScript)
               .Select(x=> (ExpandoObject)ToExpandoObject(x));

référence: problèmes dapper-dot-net 166

11
Behzad