Comment convertir la liste au type d'exécution (Liste >)

c# casting dapper dynamic-language-runtime linq

Question

J'utilise une méthode qui a un signatur de retour de IEnumerable<dynamic> . Lors de l'exécution d'un appel particulier, il renvoie la List<Dapper.SqlMapper.FastExpando> .

var x0 = repo.Find(proc, param); 
//x0 runtime type is {List<Dapper.SqlMapper.FastExpando>}

LINQPad.Extensions.Dump indique que le type d'exécution de x0 est: List<IDictionary<String, Object>> mais je n'arrive pas à convertir / convertir en List<IDictionary<String, Object>> . Voici une capture d'écran du vidage Linqpad: entrer la description de l'image ici

En fin de compte, je dois joindre toutes les valeurs de chaque dictionnaire à un seul IEnumerable<DateTime> .

IEnumerable<DateTime> GetDates(int productId) 
{
    const string proc = "[dbo].[myproc]";
    dynamic param = new { Id = "asdf" };
    var x0 = repo.Find(proc, param); 
    //...
    //linq conversion from x0 to IEnumerable<DateTime> here.
}

Erreur je reçois

List<IDictionary<String, Object>> x5 = repo.Find(proc, param);

résulte en:

RuntimeBinderException: Cannot implicitly convert type 'object' to
 'System.Collections.Generic
     .List<System.Collections.Generic.IDictionary<string,object>>'.
An explicit conversion exists (are you missing a cast?)

HISTORIQUE: J'utilise un wrapper Dapper et je ne peux pas changer la table / procédure stockée de la base de données qui renvoie des résultats dénormalisés. Au lieu de 100 lignes de 1 élément de données, le sproc renvoie 1 ligne de 100 colonnes. Je voulais éviter de créer une classe pour représenter les 100 colonnes et tirer parti de la capacité automagique de Dapper à transposer les données de colonne en lignes via un IDictionary de columnName, columnValue.

UPDATE Cela semble être un problème avec le paramètre dynamique. Lorsque spécifié en ligne, cela fonctionne. S'il est spécifié localement et passe ensuite en paramètre, il échoue.

IEnumerable<DateTime> GetDates(int productId) 
{
    const string proc = "[dbo].[myproc]";
    dynamic param = new { Id = "asdf" };

    //next line throws RuntimeBinderException: 'object' does not 
    //contain a definition for 'First'.
    //IDictionary<String, object> x0 = repo.Find(proc, param).First();

    //this succeeds:
    IDictionary<String, object> x0 = repo.Find(proc, new { Id = "asdf" }).First();

    IEnumerable<DateTime> qry2
       = x0.Values.AsQueryable()
           .Where(x => x != null)
           .Select(x => (DateTime) x);
    return qry2;
}

Voici les signatures pour Find et Query :

//Repository::Find
public IEnumerable<dynamic> Find(string procName, object param = null)

//Dapper SqlMapper::Query
public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)

Réponse populaire

Vous pouvez utiliser la méthode LINQ Cast pour convertir chaque élément de la séquence.

List<IDictionary<String, Object>> data = repo.Find(proc, param)
    .AsEnumerable()
    .Cast<IDictionary<String, Object>>()
    .ToList();


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi