Вызвать функцию на каждой записи из результата dapper

asp.net-mvc-5 c# dapper

Вопрос

Я пытаюсь вызвать функцию на каждой записи, которая установит некоторые значения полей. Когда результаты предназначены для подкачки, это достигается следующим образом:

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

Моя проблема возникает, когда результаты не предназначены для выгрузки. Мой запрос в первом примере включает разделение по столбцу, и поэтому все работает, однако мой следующий запрос представляет собой простой запрос, такой как Select Column1, Column2 FROM MyAwesomeTable который будет возвращать все строки, столбцы и т. Д. ...

Проблема в том, что мне все равно нужно применять customAction для каждого возвращаемого результата. Теперь давайте представим себе, что есть потенциал возврата нескольких миллионов записей (поверьте мне, это нереально, учитывая мою ситуацию), поэтому я не хочу снова перебирать каждую запись и применять свой метод, я хочу, чтобы этот метод применяется, когда dapper возвращает результаты, как и в первом случае.

Вот что я пробовал:

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

Я получаю сообщение об ошибке для вышеуказанного кода, что он не может разрешить метод Query<T>(etc... Я понимаю, что это потому, что его не существует. Я здесь спрашиваю, что было бы лучшим способом выполнить то, что я пытаюсь сделать Возможно ли это с помощью dapper.

Принятый ответ

Боюсь, что короткий ответ заключается в том, что вы не можете этого сделать.

Несколько более длинный ответ заключается в том, что в вашем запросе по запросу он по сути является вторым проходом через данные, поскольку Dapper выполняет некоторую работу по переводу данных каждой строки в экземпляр «T», а затем делает отдельный вызов метода «карта» которую вы используете для вызова своего «customAction».

Таким образом, было бы очень мало различий между этим и простым пропущенным вызовом «conn.Query», за которым последует последующий проход для выполнения вашего customAction. Что-то вроде следующего:

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

Если вы беспокоитесь о том, что вы можете загружать много, много записей в запросах без постраничного поиска, то стоит иметь в виду, что все эти записи будут загружены в память сразу; они не будут извлекаться из базы данных один раз в то время, когда вы перечислите возвращаемые результаты, и это может быть значительным утечкой ресурсов (если вы говорите о столь большом количестве данных, что вы хотели избежать второго перечисления) ,

Это должно быть так, потому что соединение SQL закрывается по возврату GetNonPagedQuery, и поэтому нет возможности оставить его открытым для чтения вызываемым абонентом данных «по запросу». Если вы действительно работаете с огромным количеством данных, возможно, непосещенный запрос не лучший подход?

Обратите внимание, что в приведенном выше коде «customAction» будет вызываться только при перечислении по строкам, это не все будет запущено до возврата GetNonPagedQuery. Если «customAction» потенциально является дорогостоящей операцией, это может быть полезно вам. С другой стороны, если вы хотите, чтобы функция «customAction» вызывалась для каждого результата до того, как GetNonPagedQuery вернулась, вам понадобится еще один вызов ToList () после Cast <dynamic> (), это просто зависит от того, какой сценарий вам более полезен.


Популярные ответы

Да, возможно, это:

См. Раздел документации Dapper о переключении типов в строке . Я сомневаюсь (т.е. сам не пробовал), что это не сработает, если вы использовали одну и ту же систему для массажа результатов в желаемый формат, прочитав каждую строку и обработав ее явно.



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему