2012-01-24 4 views
4

1) У меня следующие коды:"Недопустимая попытка позвонить читать, когда читатель закрыто" при использовании SqlDataReader

private static sqlDataReader gCandidateList = null; 

public SqlDataReader myCandidateList 
{ 
    set 
    { 
     gCandidateList = value; 
    } 
    get 
    { 
     return gCandidateList; 
    } 
} 

2) В Forma у меня есть:

sqlConn.ConnectionString = mySettings.myConnString; 
sqlConn.Open(); 
SqlCommand cmdAvailableCandidate = new SqlCommand(tempString, sqlConn); 
SqlDataReader drAvailableCandidate = cmdAvailableCandidate.ExecuteReader(); 
mySettings.myCandidateList = drAvailableCandidate; 
sqlConn.Close(); 

3) В FormB Я хочу, чтобы повторно использовать данные, сохраненные в myCandidatList, поэтому я использую:

SqlDataReader drCandidate = mySettings.myCandidateList; 
drCandidate.Read(); 

4), то я получил ошибку «попытка Invalide вызвать Read, когда читатель закрыто."

5) Я попробовал mySettings.myCandidateList.Read() в (3) выше и снова получил то же сообщение об ошибке.

6) Как я могу повторно открыть SqlDataReader drCandidate для чтения данных?

7) Большое спасибо за консультацию и помощь, пожалуйста.

+3

Статический DataReader никогда не является хорошей идеей. – SLaks

ответ

6

Вы не можете прочитать читатель после подключения closed или disposed. Если вы хотите использовать эти строки (результат выборки) позже в своем коде, вам необходимо создать List или DataTable.

Например,

System.Data.DataTable dt = new System.Data.DataTable(); 
dt.Load(drAvailableCandidate); 
0

Вы закрытия соединения, прежде чем пытаться прочитать от читателя. Это не сработает.

0

Когда вы вызываете Close на объекте SqlConnection (sqlConn.Close();), он закрывает соединение и ваш считыватель данных. Вот почему вы получаете сообщение об ошибке при попытке прочитать из своего SqlDataReader из FormB.

Что вам нужно сделать, это изменить определение вашего свойства myCandidateList, чтобы вместо этого вернуть представление данных, которые вы извлекли из своего читателя drAvailableCandidate.

По существу, вам необходимо выполнить итерацию по строкам в объекте drAvailableCandidate, извлечь значения и кешировать их в свойстве для последующего извлечения.

1

Если вы хотите использовать datareader на более позднем этапе, вы должны указать то же, что и параметр, для метода ExecuteReader. Ваш код в FormA должен быть изменен, как показано ниже.

sqlConn.ConnectionString = mySettings.myConnString; 
sqlConn.Open(); 
SqlCommand cmdAvailableCandidate = new SqlCommand(tempString, sqlConn); 
SqlDataReader drAvailableCandidate = cmdAvailableCandidate.ExecuteReader(CommandBehavior.CloseConnection); 
mySettings.myCandidateList = drAvailableCandidate; 
sqlConn.Close(); 

Убедитесь распоряжаться DataReader, когда он используется, как подключение к базе данных будет проводиться открытым, пока DataReader закрыт. Лучше измените свой код в FormB, как показано ниже.

using (mySettings.myCandidateList) 
{ 
mySettings.myCandidateList.Read(); 
} 
0

Просто, чтобы добавить к ответам уже данным, если вы используете асинхр/ждать, то это легко увязнуть с этим, не ожидая операции внутри с помощью блока в SqlConnection. Например, выполнив следующие действия могут дать сообщили об ошибке

public Task GetData() 
{ 
    using(new SqlConnection(connString)) 
    { 
     return SomeAsyncOperation(); 
    } 
} 

Проблема здесь в том, что мы не ожидали операций внутри использования, поэтому он быть утилизирован, прежде чем мы на самом деле выполнить операцию сошки асинхронной. Чрезвычайно очевидно, но догнал меня раньше.

Правильная вещь, которую нужно сделать, чтобы ждать внутри использования.

public async Task GetData() 
{ 
    using(new SqlConnection(connString)) 
    { 
     await SomeAsyncOperation(); 
    } 
} 
Смежные вопросы