Cómo convertir la lista al tipo de tiempo de ejecución (Lista >)

c# casting dapper dynamic-language-runtime linq

Pregunta

Estoy usando un método que tiene un signo de retorno de IEnumerable<dynamic> . En el tiempo de ejecución para una llamada en particular, devuelve List<Dapper.SqlMapper.FastExpando> .

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

LINQPad.Extensions.Dump indica que el tipo de tiempo de ejecución de x0 es: List<IDictionary<String, Object>> pero parece que no puedo convertir / convertir a List<IDictionary<String, Object>> . Aquí hay una captura de pantalla del Volcado de Linqpad: enter image description here

En última instancia, necesito unir todos los valores de cada diccionario a un único 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.
}

Error que estoy recibiendo

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

resultados 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?)

ANTECEDENTES: Estoy usando un contenedor Dapper y no puedo cambiar la tabla de la base de datos / procedimiento almacenado que devuelve resultados desnormalizados. En lugar de 100 filas de 1 elemento de datos, el sproc devuelve 1 fila de 100 columnas. Quería evitar crear una clase para representar las 100 columnas y aprovechar la capacidad automotriz de Dapper para transponer los datos de la columna a filas a través de IDictionary de columnName, columnValue.

ACTUALIZACIÓN Esto parece ser un problema con el parámetro dinámico. Cuando se especifica en línea, funciona. Si se especifica localmente y luego pasa como un parámetro, falla.

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

Aquí están las firmas para Find y 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)

Respuesta popular

Puede usar el método LINQ Cast para convertir cada elemento en la secuencia.

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


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