I have a method to execute an SQL statement and it returns an instance of my class ResultSet that contains the rows and columns returned. I only want to read the data row-by-row when the caller actually iterates over the results.
public class ResultSet {
public IEnumerable<Row> Rows {
get;
private set;
}
public ResultSet(IEnumerable<Row> rows, IEnumerable<Column> columns) {
Rows = rows;
// columns and other code omitted
}
}
For this, I tried passing an IEnumerable to the constructor of my class, but the problem is that the DbDataReader instance has already been disposed by the time you try to iterate over the Rows property of a ResultSet instance:
public ResultSet Execute(string sql) {
using (var command = Connection.CreateCommand()) {
command.CommandText = sql;
var reader = command.ExecuteReader();
try {
IEnumerable<Row> MyFunc()
{
while (reader.Read())
yield return new Row(reader);
}
var columns = GetColums(...);
return new ResultSet(MyFunc(), columns);
} finally {
reader.Dispose();
}
}
}
I know I could pass the DbDataReader instance to my class and not dispose it in the Execute method but then I would have to make ResultSet disposable and I would like to avoid that, if possible. I'm not sure it's even possible what I'm trying to do?
I have looked at yield return statement inside a using() { } block Disposes before executing but it's not quite the same as it doesn't involve a disposable resources.
IEnumerablethat callsExecuteReaderwhenGetEnumeratoris called, and no earlier. (Iterator methods can returnIEnumeratoras well, so this isn't as troublesome as it sounds.) Or, always an option, give this kind of manual ORM code a pass and use Dapper, which tends to fit these sorts of scenarios quite well. - Jeroen MostertIEnumerable<Row>building customIEnumerator<Row>that execute the query the first timeMoveNextis called. - vc 74yield? (disclaimer: I dislikeyield). - JuanR