Страницы

Поиск по вопросам

четверг, 25 октября 2018 г.

There is already an open DataReader associated with this Connection which must be closed first

Есть следующий метод:
public static bool IfStudentHasProblems(CollegeContext db, Student student, ControlPoint cp) { foreach (var mark in db.Marks.Where(m => m.Student.StudentId == student.StudentId)) { if (mark.ControlPoint == cp && mark.Value < 4) return true; } return false; }
При обращении к db.Marks выбрасывает исключкение выше. Код вызывающий метод:
private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (groupComboBox.SelectedIndex != 0) { int num = Convert.ToInt32(groupComboBox.SelectedItem); selectedGroup = db.Groups.FirstOrDefault(g => g.Number == num);
studentListView.Items.Clear(); foreach (var student in db.Students.Where(s => s.Group.Number == selectedGroup.Number).OrderBy(s => s.LastName).ThenBy(s => s.FirstName)) if (CalculationUtils.IfStudentHasProblems(db, student, selectedCP)) studentListView.Items.Add(student.LastName + " " + student.FirstName).BackColor = Color.Goldenrod; else studentListView.Items.Add(student.LastName + " " + student.FirstName);
if (selectedCP != null) WriteStatistics(); } else { selectedGroup = null; studentListView.Items.Clear(); } }
Так же есть похожий метод, который выполняется без ошибок:
public static int CountStudentsWithBadMarks(CollegeContext db, Group group, ControlPoint cp) { int c = 0; foreach (var m in db.Marks.Where(m => m.Student.Group.Number == group.Number)) if (m.ControlPoint.Date == cp.Date) if (m.Value < 4) c++; return c; }
Помогите пожалуйста разобраться, где ошибка и как исправить.


Ответ

Такое происходит потому что вы пытаетесь делать один запрос к БД в то время пока идет перебор результатов другого запроса к БД.
Если посмотреть какие запросы к БД вы делаете, то получится как-то вот так:
foreach (var student in db.Students.Where(...)) { foreach (var mark in db.Marks.Where(m => m.Student.StudentId == student.StudentId)) { // ... } }
Исправить проблему можно несколькими способами:
(не работает для MySQL) разрешить соединению иметь несколько открытых дата ридеров - добавить MultipleActiveResultSets=true в строку подключения к БД; материализовать внешний запрос
foreach (var student in db.Students.Where(...).ToList()) { foreach (var mark in db.Marks.Where(m => m.Student.StudentId == student.StudentId)) { // ... } } использовать навигационные свойства вместо дополнительных запросов совместно с eager loading:
foreach (var student in db.Students.Where(...).Include(s => s.Marks)) { foreach (var mark in student.Marks) { // ... } }

Комментариев нет:

Отправить комментарий