Устройство чтения данных asp.net должно быть закрыто - PullRequest
2 голосов
/ 14 декабря 2011

Мой код:

SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString);
SqlCommand cmd = new SqlCommand();
//..........
cmd.CommandText = "SELECT * FROM TempQn WHERE creatorId=  '" +
Session["administratorID"].ToString() + "'";  
dr = cmd.ExecuteReader();  
while (dr.Read())
{
    int ids = Int32.Parse(dr["QuestionID"].ToString());
    cmd.CommandText = " INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ";
    cmd.ExecuteNonQuery(); //this line
}
dr.Close();

Ошибка:

Уже существует открытый DataReader, связанный с этой командой, который должен быть закрыт первым.

Какая команда должна заменить cmd.ExecuteNonQuery();?

Ответы [ 5 ]

3 голосов
/ 14 декабря 2011

Вы не можете выполнять дальнейшие операторы SQL, пока DataReader "активен".

Чтобы преодолеть это, сохраните список операторов SQL, а затем выполните их после чтения:

cmd.CommandText = "SELECT * FROM Question WHERE SurveyID= '" + sID + "'";    
dr = cmd.ExecuteReader();  
List<string> arrSQL = new List<string>();
while (dr.Read())
{
    int ids = Int32.Parse(dr["QuestionID"].ToString());
    arrSQL.Add("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ");
}
dr.Close();

arrSQL.ForEach(strSQL =>
{
    cmd.CommandText = strSQL;
    cmd.ExecuteNonQuery();
});

Ваш текущий код уязвим для атак с использованием SQL-инъекций и не является хорошей практикой - вам лучше использовать параметр вместо введения значения в необработанный SQL - вот как этого добиться:

cmd.CommandText = "SELECT * FROM Question WHERE SurveyID=@id";
cmd.Parameters.AddWithValue("@id", sID);
dr = cmd.ExecuteReader();  
List<int> arrQuestions = new List<int>();
while (dr.Read())
{
    int ids = Int32.Parse(dr["QuestionID"].ToString());
    arrQuestions.Add(ids);
}
dr.Close();

cmd.CommandText =  "INSERT INTO Answers (QuestionId, Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = @id";
arrQuestions.ForEach(id =>
{
    cmd.Parameters["@id"].Value = id;
    cmd.ExecuteNonQuery();
});
1 голос
/ 14 декабря 2011

Вместо использования второго объекта подключения вы можете изменить строку подключения и использовать для этой цели MARS ( Множественный активный набор результатов ).Добавьте следующий оператор в строку подключения:

MultipleActiveResultSets=True

EDIT: И, как сказал другой, используйте SqlParameters для ваших параметров, а не конкатенацию строк.Это не только проблема безопасности, но и огромный удар по производительности!

1 голос
/ 14 декабря 2011

Этот единственный запрос должен выполнять свою работу (не уверен в точной модели данных, адаптируйся при необходимости):

INSERT INTO Answers (QuestionId,Answer) 
Select c.QnId, c.Answer 
From TempAns c 
inner join Question q on c.QnId = q.Id
where q.SurveyID = @SurveyID

Чтобы избежать SQl Injection, используйте этот код C #:

cmd.CommandTest = @"INSERT INTO Answers (QuestionId,Answer) 
    Select c.QnId, c.Answer 
    From TempAns c 
    inner join Question q on c.QnId = q.Id
    where q.SurveyID = @SurveyID";

SqlParameter param = cmd.Parameters.Add("@SurveyID", SqlDbType.Int);
param.Value = yourSurveyId;

cmd.Open(); // it would be better to check the status before 
cmd.ExecuteNonQuery();
cmd.Close();
1 голос
/ 14 декабря 2011

У вас уже есть одна команда, связанная с "cmd".

  dr = cmd.ExecuteReader();  
          while (dr.Read())
          {
              int ids = Int32.Parse(dr["QuestionID"].ToString());
              SqlCommand sqlCmd = new SqlCommand("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ");
              sqlCmd.ExecuteNonQuery(); //this line
          }
          dr.Close();

Так же, как в приведенном выше примере, создайте новую команду для вставки.

0 голосов
/ 14 декабря 2011

вам нужно объявить новый объект команды, потому что cmd уже используется для чтения данных, когда вы пытаетесь использовать его для оператора вставки.Кроме того, не используйте конкатенацию строк из команды sql, это плохая практика и уязвимо для внедрения SQL.используя параметры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...