Llamar a una función en cada registro desde el resultado apuesto

asp.net-mvc-5 c# dapper

Pregunta

Intento llamar a una función en cada registro que establecerá algunos valores de campo. Cuando se pretende paginar los resultados, esto se logra de la siguiente manera:

public IDataWrapper GetPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper ();
    using (var oConn = CreateConnection(ConnectionString))
    {
        TotalPages totalRows = null;
        var list = oConn.Query<T, TotalPages, T>(myQuery, (e, t) =>
        {
            totalRows = t;
            if (mapAction != null) customAction(e);
            return e;
        }, param, splitOn: "SplitOn");
        obj.RowsFound = (IEnumerable<dynamic>)list;
        obj.TotalRows = totalRows == null ? 0 : totalRows.TotalRows;
    }
    return obj;
}

Mi problema viene cuando los resultados no están destinados a ser paginado. Mi consulta en el primer ejemplo incluye división en columna y esta es la razón por la que funciona, sin embargo, mi próxima consulta es una consulta simple, como Select Column1, Column2 FROM MyAwesomeTable que devolverá todas las filas, columnas, etc.

El problema es que aún necesito aplicar CustomAction en cada resultado que se devuelve. Ahora imaginemos, que hay un potencial de pocos millones de registros que vuelven (créanme, esto no es poco realista dada mi situación), como tal, no quiero volver a recorrer cada registro de nuevo y aplicar mi método, quiero ese método aplicado como el dapper está devolviendo resultados, al igual que en el primer caso.

Esto es lo que intenté:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper ();
    using (var oConn = CreateConnection(ConnectionString))
    {
        var list = oConn.Query<T>(myQuery, (e) =>
        {
            if (mapAction != null) customAction(e);
            return e;
        }, param).ToList();
        obj.RowsFound = (IEnumerable<dynamic>)list;
        obj.TotalRows = list.Count();
    }
    return obj;
}

Me sale un error del código anterior que no puede resolver el método Query<T>(etc... Entiendo que es porque no existe. Estoy aquí preguntando cuál sería la mejor manera de lograr lo que intento hacer ? Es posible con dapper.

Respuesta aceptada

Me temo que la respuesta corta es que no puedes hacer esto.

La respuesta ligeramente más largo es que en la consulta paginado, que, esencialmente, es un segundo paso por los datos desde Dapper hace algún trabajo de traducir los datos de cada fila en una instancia de "T" y entonces se hace una llamada independiente al método de "mapa" que utilizas para llamar a tu "acción personalizada".

Por lo tanto, habría muy poca diferencia entre eso y hacer una simple llamada "conn.Query" no paginada seguida de un pase posterior para ejecutar su acción personalizada. Algo como lo siguiente:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper();
    using (var oConn = CreateConnection(ConnectionString))
    {
        var results = oConn
            .Query<T>(myQuery)
            .ToList();
        obj.TotalRows = results.Count();
        obj.RowsFound = results
            .Select(value =>
            {
                customAction(value);
                return value;
            })
            .Cast<dynamic>();
    }
    return obj;
}

Si le preocupa que pueda estar cargando muchos, muchos registros en la consulta no paginada, entonces vale la pena tener en cuenta que todos esos registros se cargarán en la memoria a la vez; no se extraerán de la base de datos una a la vez como su enumeración sobre los resultados devueltos y esto podría ser una pérdida considerable de recursos (si está hablando de tantos datos que quería evitar una segunda enumeración) .

Este debe ser el caso porque la conexión SQL se cierra cuando GetNonPagedQuery regresa y, por lo tanto, no hay forma de que se pueda dejar abierta para que la persona que llama pueda leer los datos "a petición". Si realmente está trabajando con cantidades masivas de datos, tal vez una consulta no paginada no sea el mejor enfoque.

Tenga en cuenta que en el código anterior, la "acción personalizada" solo se invocará mientras enumera en las filas, no se dispararán todas antes de que GetNonPagedQuery regrese. Si "acción personalizada" es potencialmente una operación costosa, esto puede beneficiarlo. Por otro lado, si desea llamar a "acción personalizada" para cada resultado antes de que GetNonPagedQuery regrese, entonces necesitaría una llamada más ToList () después de Cast <dynamic> (), solo depende de qué escenario le sea más útil.


Respuesta popular

Sí, posiblemente sea:

Consulte la sección de los documentos de Dapper sobre el cambio de tipos por fila . Dudo (es decir, no lo intenté) que no funcionaría si usabas el mismo sistema para dar masajes a los resultados en el formato que deseas leyendo cada fila y procesándola de forma explícita.



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é