0

Конкретным новичком себя назвать не могу, раньше уже с С# дело имела, как и с DataGridView (дальше DGV), но раньше до скорости загрузки данных дела не было (данных было мало, да и сами БД по структуре были достаточно простые), а вот сейчас стал вопрос ускорения загрузки данных в DGV. Скажу сразу, что в коде не использую запросы SQL, в качестве БД использую Firebase.

Сейчас использую такую конструкцию:

Формирование столбцов таблицы:

            dt.Columns.Add("ID");
            dt.Columns.Add("КЗ");
            dt.Columns.Add("ДЗ");
            dt.Columns.Add("Студент");
            dt.Columns.Add("Дисципліна");
            dt.Columns.Add("Тип");
            dt.Columns.Add("Дата");
            UploadTable();

Собственно сама загрузка данных в DGV (вернее, код автоматического обновления таблицы после создания/обновления/удаления оценок):

            List<BLL.DTOs.MarkDTO> temp = marksService.GetMarksByInstitute(institute);
            dt.Rows.Clear();
        foreach (var elem in temp)
        {
            DataRow row = dt.NewRow();
            row[&quot;ID&quot;] = elem.ID;
            row[&quot;КЗ&quot;] = elem.Short_Value;
            row[&quot;ДЗ&quot;] = elem.Long_Value;
            row[&quot;Студент&quot;] = studentsService.GetFIOByID(elem.Student_ID);
            row[&quot;Дисципліна&quot;] = 
            disciplinesService.GetNameById(elem.Discipline_ID);
            row[&quot;Тип&quot;] = elem.Type;
            row[&quot;Дата&quot;] = elem.Date;

            dt.Rows.Add(row);
        }

        DataView dataView = new DataView(dt);
        dataGridView1.DataSource = dataView;

При такой конструкции загрузка 20-25 записей занимает около 12-14 секунд, что явно многовато, учитывая, что записей по плану будет явно больше чем 20. Немного изменив код:

            dt.Columns.Add("ID");
            dt.Columns.Add("КЗ");
            dt.Columns.Add("ДЗ");
            dt.Columns.Add("Студент");
            dt.Columns.Add("Дисципліна");
            dt.Columns.Add("Тип");
            dt.Columns.Add("Дата");
            dataGridView1.DataSource = dt;
            UploadTable();
List<BLL.DTOs.MarkDTO> temp = marksService.GetMarksByInstitute(institute);
            dt.Rows.Clear();
            foreach (var elem in temp)
            {
                DataRow row = dt.NewRow();
                row["ID"] = elem.ID;
                row["КЗ"] = elem.Short_Value;
                row["ДЗ"] = elem.Long_Value;
                row["Студент"] = studentsService.GetFIOByID(elem.Student_ID);
                row["Дисципліна"] = disciplinesService.GetNameById(elem.Discipline_ID);
                row["Тип"] = elem.Type;
                row["Дата"] = elem.Date;
            dt.Rows.Add(row);
        }

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

Понимаю, что, скорее всего, решение простое, но я реально пока не знаю что делать. Очень хочется, что бы результаты прогружались достаточно быстро (в пределах 3 секунд, в идеале).

Иными словами, есть список оценок (второй фрагмент кода, переменная temp), и нужно быстро перенести его в DGV.

Функция UploadTable - это как раз тот второй кусок кода.

Данные сервисы получают данные с одной и той же удаленной БД (я упоминала Firebase).

Я тоже сначала проверила именно сервисы, но их я уже изменила, и они запросы выполняют достаточно быстро.

Основная проблема - именно с отрисовкой самой таблицы. Вариантом присвоения списка свойству DataSource я воспользовалась, и теперь таблица прогружается и обновляется реально быстро (1-2 секунды) даже при большом кол-тве данных, но появилось два нюанса - столбцы переименовались с нормальных названий на названия полей, и значения в строках повторяет в точности значения объектов в списке.

Вопрос с названиями столбцов решился (топорно, правда, но работает) - я просто в коде создаю столбцы.

dataGridView1.Columns.AddRange(
        new DataGridViewTextBoxColumn() { Name = "clmID", HeaderText = "ID", DataPropertyName = "ID" },
        new DataGridViewTextBoxColumn() { Name = "clmShortValue", HeaderText = "КЗ", DataPropertyName = "Short_Value" },
        new DataGridViewTextBoxColumn() { Name = "clmLongValue", HeaderText = "ДЗ", DataPropertyName = "Long_Value" },
        new DataGridViewTextBoxColumn() { Name = "clmStudent", HeaderText = "Студент", DataPropertyName = "Student_ID" },
        new DataGridViewTextBoxColumn() { Name = "clmDiscipline", HeaderText = "Дисципліна", DataPropertyName = "Discipline_ID" },
        new DataGridViewTextBoxColumn() { Name = "clmType", HeaderText = "Тип", DataPropertyName = "Type" },
        new DataGridViewTextBoxColumn() { Name = "clmDate", HeaderText = "Дата", DataPropertyName = "Date" },
        new DataGridViewTextBoxColumn() { Name = "clmTeacher", HeaderText = "Викладач", DataPropertyName = "Teacher_ID" }
        );

Что до основной проблемы (скорость), то да, обращений действительно много (и там циклы, что замедляет работу). Решение вижу в Linq, так что буду рефакторить остальной код приложения.

  • Если уже есть список, то делаем просто dataGridView1.DataSource = temp;. Если нужна двусторонняя привязка (two-way binding), то вместо List<T> используем BindingList<T>. – Alexander Petrov Dec 25 '22 at 14:35
  • Что именно работает медленно? Вот эти ваши сервисы: marksService, studentsService, disciplinesService - обращение к ним тормозит? Откуда они получают данные? Если из разных мест, то единственно, что можно предложить - кэшировать данные. Однако, полагаю, они все обращаются к одной и той же базе данных. Тогда вместо них следует использовать один sql-запрос с объединением (Join) нескольких таблиц - это будет работать действительно быстро. – Alexander Petrov Dec 25 '22 at 14:38
  • Вы упорно показываете вызов какого-то метода UploadTable();. Для чего? Что он делает? Не он ли тормозит? – Alexander Petrov Dec 25 '22 at 14:39
  • Не пишите в комментариях. Редактируйте вопрос. – Alexander Petrov Dec 25 '22 at 15:13
  • Вопрос отредактировала. – Ксения Манжула Dec 25 '22 at 15:23
  • Основная проблема - именно с отрисовкой самой таблицы - Проблемы с отрисовкой решаются включением двойной буферизации. Но ваша проблема вовсе не в этом. – Alexander Petrov Dec 25 '22 at 18:36
  • столбцы переименовались - это другой вопрос и для решения это проблемы следует создать новую тему. Таковы правила этого сайта: один вопрос - одна тема. P. S. Решается это с помощью свойства DataPropertyName – Alexander Petrov Dec 25 '22 at 18:38
  • 1
    Переходим к сути вопроса. Ваш код работает медленно, потому что выполняется множество запросов в БД. studentsService.GetFIOByID, disciplinesService.GetNameById выполняются в цикле, много раз. В большинстве бизнес-приложений узким местом является работа с БД. Правильное решение: использовать один sql-запрос с join для получения всех необходимых данных. – Alexander Petrov Dec 25 '22 at 18:41
  • https://ru.stackoverflow.com/a/1199692/373567, для того чтобы DGV не тормозила, можно включить DoubleBuffered, здесь есть пример. По поводу БД, старайтесь получать все необходимые данные одним запросом, а у вас из тут очень много выполняется. – aepot Dec 27 '22 at 04:32

0 Answers0