2010-10-22 2 views
2

Интересная проблема, с которой я столкнулся, которая имеет общий смысл. У меня есть универсальный метод, как так:Возврат 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 внутри делегата, но еще раз, если я могу избежать этого для каждого делегата, было бы неплохо. Любые идеи?

ответ

5

Возможно:

public TResult Run<TResult>(Func<SqlDataReader, TResult> resultDelegate) 
{ 
    TResult result; 

    using (SqlDataReader reader = command.ExecuteReader()) // command is SqlCommand with attached SqlConnection 
    { 
     result = resultsDelegate(reader); 
     if (typeof(TResult) == typeof(IEnumerable<object>)) 
     { 
     var enumerable = result as IEnumerable<object>; 
     if (enumerable != null) 
     { 
      result = enumerable.ToList(); 
     } 
     } 
    } 

    // Some other unrelated code (but that's why result has a variable) 

    return result; 

} 
+0

Интересная идея - вы заставляете ее быть конкретным списком, но вне сферы компетенции делегата. Думаю, в этом случае это ха s скрытые и непреднамеренные последствия (список должен быть выделен в памяти). Если бы мне пришлось пройти этот маршрут, я бы, скорее всего, выбросил исключение, если делегат вернет IEnumerable; таким образом очевидно, что действительно происходит. –

+0

kudos JeffN825 за очень творческий ответ. – pstrjds

+0

Если вы не открываете свой читатель, вообще нет возможности использовать отложенное выполнение. Вы ДОЛЖНЫ выделять и перечислять результаты в объеме читателя. – Jeff

Смежные вопросы