Интересная проблема, с которой я столкнулся, которая имеет общий смысл. У меня есть универсальный метод, как так:Возврат IEnumerable с использованием
public TResult Run<TResult>(Func<SqlDataReader, TResult> resultDelegate)
{
TResult result;
using (SqlDataReader reader = command.ExecuteReader()) // command is SqlCommand with attached SqlConnection
{
result = resultsDelegate(reader);
}
// Some other unrelated code (but that's why result has a variable)
return result;
}
В одном случае, тип возвращают resultDelegate
«s (TResult
) является IEnumerable<object>
. Проблема в том, что функция Run
немедленно возвращается из-за отложенного выполнения, избавляя SqlDataReader. Позже в коде, когда я пытаюсь прочитать результаты (которые делегат делает reader.Read()
, я получаю InvalidOperationException: Invalid attempt to call Read when reader is closed.
Мне сложно найти оптимальный способ обойти это. Я знаю, что могу вернуть конкретный список , но я хотел бы избежать этого, если это возможно. Я также могу переместить оператор using внутри делегата, но еще раз, если я могу избежать этого для каждого делегата, было бы неплохо. Любые идеи?
Интересная идея - вы заставляете ее быть конкретным списком, но вне сферы компетенции делегата. Думаю, в этом случае это ха s скрытые и непреднамеренные последствия (список должен быть выделен в памяти). Если бы мне пришлось пройти этот маршрут, я бы, скорее всего, выбросил исключение, если делегат вернет IEnumerable; таким образом очевидно, что действительно происходит. –
kudos JeffN825 за очень творческий ответ. – pstrjds
Если вы не открываете свой читатель, вообще нет возможности использовать отложенное выполнение. Вы ДОЛЖНЫ выделять и перечислять результаты в объеме читателя. – Jeff