2013-04-23 5 views
1

У меня есть метод, который возвращает устройство чтения данных. Обычно я бы обернул использование вокруг считывателя данных так, чтобы он удобно располагался после того, как я прокрутил его. Проблема в том, что я решил использовать устройство чтения данных с помощью Linq, а это означает, что отсроченное выполнение заставляет читателя удаляться рано. Есть ли правильный образец для использования и утилизации устройства чтения данных с использованием Linq без необходимости создания полной коллекции его содержимого?Как лучше очистить SQLDataReader при использовании linq

using (System.Data.SqlClient.SqlDataReader reader = CallStoredProcedure()) 
{ 
    return reader.Cast<System.Data.Common.DbDataRecord>().Select(rec => new ObjectModel.CollectorSummaryItem() 
    { 
     CollectorID = (int)rec[0], 
     Name = rec.IsDBNull(1) ? null : rec.GetString(1), 
     Information = rec.IsDBNull(2) ? null : rec.GetString(2) 
    }); 
} 
+0

Вы попробовали просто делегировать чтение? Создайте метод, который принимает IDataRecord и создает ваш объект. Сформировать список и вернуть этот список? – Sinaesthetic

ответ

8

Вы должны фактически читать читателя внутри с помощью блока:

using (System.Data.SqlClient.SqlDataReader reader = CallStoredProcedure()) 
{ 
    while (reader.Read()) 
    { 
     yield return new ObjectModel.CollectorSummaryItem() 
     { 
      CollectorID = (int)reader[0], 
      Name = reader.IsDBNull(1) ? null : reader.GetString(1), 
      Information = reader.IsDBNull(2) ? null : reader.GetString(2) 
     }; 
    } 
} 

Это будет оценивать закодировать с таким же или последовательного типа возвращения с, что было раньше, но не закрывается читатель до после вы закончили читать с него.

0

Съемка с бедра здесь. Это также должно помочь вам разделить логику читателя.

public IEnumerable<MyObject> ExecuteNonQuery(...) 
{ 
    ... 
    using(var reader = comm.ExecuteReader()) 
    { 
    var results = new List<MyObject>(); 
    return reader 
      .Cast<System.Data.Common.DbDataRecord>() 
      .Select(rec => GetFromReader(rec)) 
      .ToList(); 
    } 
} 

public MyObject GetFromReader(IDataRecord rdr) 
{ 
    return new MyObject { Prop1 = rdr["prop1"], Prop2 = rdr["prop2"] }; 
} 
+0

Существует небольшая проблема с этим кодом. LINQ ленив и не будет оценивать выражение лямбда до тех пор, пока вы не перечислите «IEnumerable», который, вероятно, будет за пределами данного метода. К тому времени оператор 'using' избавился бы от' читателя'. Если вы использовали метод, подобный 'ToList()' после оператора 'Select', чтобы заставить перечисление' IEnumerable' внутри блока 'using', это может сработать. –

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