Ошибка: неверная попытка вызвать Read, когда программа чтения закрывается после цикла while?

Здравствуйте, у меня есть метод, который считывает некоторые данные из sql и сохраняет их в массивы.

чтобы узнать, сколько строк имеет результат sql, я написал это:

DataTable dt = new DataTable();
            dt.Load(rdr);
            count = dt.Rows.Count;

после этого sqldatareader сохраняет результаты в массивы.

вот мой полный код:

 public BookingUpdate[] getBookingUpdates(string token)
{
    String command = "SELECT b.ID,b.VERANSTALTER, rr.VON ,rr.BIS, b.THEMA, b.STORNO, ra.BEZEICHNUNG from BUCHUNG b JOIN RESERVIERUNGRAUM rr on rr.BUCHUNG_ID = b.ID JOIN RAUM ra on ra.ID = rr.RAUM_ID WHERE b.UPDATE_DATE BETWEEN DATEADD (DAY , -20 , getdate()) AND getdate() AND b.BOOKVERNR = 0";
    SqlConnection connection = new SqlConnection(GetConnectionString());
    BookingUpdate[] bookingupdate = new BookingUpdate[1];
    connection.Open();
    try
    {
        SqlCommand cmd = new SqlCommand(command, connection);
        SqlDataReader rdr = null;
        int count = 0;
        int c = 0;

        rdr = cmd.ExecuteReader();
        DataTable dt = new DataTable();
        dt.Load(rdr);
        count = dt.Rows.Count;
        bookingupdate = new BookingUpdate[count];

        while (rdr.Read())   // <--- HERE COMES THE ERROR
        {
                bookingupdate[c] = new BookingUpdate();
                bookingupdate[c].bookingID = Convert.ToInt32(rdr["ID"]);
                bookingupdate[c].fullUserName = rdr["VERANSTALTER"].ToString();
                bookingupdate[c].newStart = (DateTime)rdr["VON"];
                bookingupdate[c].newEnd = (DateTime)rdr["BIS"];
                bookingupdate[c].newSubject = rdr["THEMA"].ToString();
                bookingupdate[c].newlocation = rdr["BEZEICHNUNG"].ToString();
                if (rdr["STORNO"].ToString() != null)
                {
                    bookingupdate[c].deleted = true;
                }
                else
                {
                    bookingupdate[c].deleted = false;
                }
                c++;

        }
    }

    catch (Exception ex)
    {
        log.Error(ex.Message + "\n\rStackTrace:\n\r" + ex.StackTrace);
    }
    finally
    {
        connection.Close();
    }
    return bookingupdate;
}

исключение: неверная попытка вызвать чтение, когда читатель закрыт


person Eray Geveci    schedule 14.02.2013    source источник
comment
На какую строку падает ошибка?   -  person DGibbs    schedule 14.02.2013
comment
Тот же вопрос с stackoverflow.com/questions/14849780 / ??   -  person Soner Gönül    schedule 14.02.2013
comment
это другой вопрос с тем же методом   -  person Eray Geveci    schedule 14.02.2013


Ответы (3)


Метод Load закрывает DataReader, поэтому следующий вызов Read() завершается ошибкой. (ну, это именно то, что говорит вам исключение).

Как только вы прочитаете данные в свой DataTable, вы можете просто запросить их и использовать проекцию Select для создания экземпляров BookingUpdate (нет необходимости в цикле while/BookingUpdate[]). Таким образом, ваш код можно в основном сократить до

String command = "SELECT b.ID,b.VERANSTALTER, rr.VON ,rr.BIS, b.THEMA, b.STORNO, ra.BEZEICHNUNG from BUCHUNG b JOIN RESERVIERUNGRAUM rr on rr.BUCHUNG_ID = b.ID JOIN RAUM ra on ra.ID = rr.RAUM_ID WHERE b.UPDATE_DATE BETWEEN DATEADD (DAY , -20 , getdate()) AND getdate() AND b.BOOKVERNR = 0";
SqlCommand cmd = new SqlCommand(command, new SqlConnection(GetConnectionString()));
connection.Open();

DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());

var bookingupdate = dt.Rows.OfType<DataRow>().Select (row => 
                    new BookingUpdate
                    {
                        bookingID = Convert.ToInt32(row["ID"]),
                        fullUserName = row["VERANSTALTER"].ToString(),
                        newStart = (DateTime)row["VON"],
                        newEnd = (DateTime)row["BIS"],
                        newSubject = row["THEMA"].ToString(),
                        newlocation = row["BEZEICHNUNG"].ToString(),
                        deleted = row["STORNO"].ToString() != null // note that this line makes no sense. If you can call `ToString` on an object, it is not 'null'
                    }).ToArray();

return bookingupdate;

(Примечание: я опустил блок try для удобства чтения)

Вы также можете изучить DataRowExtensions, особенно Field, чтобы сделать ваш код более читабельным.

person sloth    schedule 14.02.2013

DataTable.Load(IDataReader) закрывает ридер после загрузки из него данных. Используйте DataTable для получения загруженных данных.

person gzaxx    schedule 14.02.2013

Вы уже обработали считыватель в следующей строке, из-за которого считыватель находится в EOF/Closed:

dt.Load(rdr);

Если вы хотите обработать записи после вызова вышеуказанного метода, вы должны использовать созданный вами DataTable объект dt в приведенной выше строке unsing for loop с dt.Rows.Count вместо while (rdr.Read())

Ознакомьтесь с этой темой на сайте MSDN.

person VSS    schedule 14.02.2013