Модераторы: gambit, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как наиболее быстро загрузить TreeView из БД 
:(
    Опции темы
Softaz
Дата 9.11.2006, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 3
Всего: 16



Вот мой код:
Файл БД взят из DOTNET_Browser: http://forum.vingrad.ru/topic-104564/0.html (3-я и последующие версии).
Скорость примерно 2500 Нод за 18 секунд. Если эта скорость нормальна, то все в порядке.
В принципе, наверное, будет быстрее, если сначала загрузить в DataSet все, а потом из него брать (из памяти, а не из файла БД), но у меня скорость практически не изменилась.
Склейка SQL-запросов пусть останется - не пинайте. Думаю, данные строго типизированы.
Код

#region TreeView

public class MyTree
{
    public void BuildTreeView(TreeView tv, ImageList il, ToolStripStatusLabel lb)
    {
        int col = 1;
        tv.Nodes.Clear();
        tv.ImageList = il;
        tv.SelectedImageIndex = 3;

        #region Заполнение A
        string command_a = "Select * from kategory ORDER BY kategory";
        System.Data.OleDb.OleDbDataAdapter adapter_a = new System.Data.OleDb.OleDbDataAdapter(command_a, global::Netcode.Properties.Settings.Default.csanConnectionString);
        System.Data.DataSet topics = new System.Data.DataSet();
        adapter_a.Fill(topics, "kategory");
        #endregion

        for (int i = 0; i < topics.Tables["kategory"].Rows.Count; i++)
        {
            tv.Nodes.Add("", topics.Tables["kategory"].Rows[i]["kategory"].ToString(), 0);
            Application.DoEvents();

            #region Заполнение B
            string command_b = "Select * from sub_kategory WHERE sub_kategory.id_k = " + topics.Tables["kategory"].Rows[i]["id_k"].ToString() + " ORDER BY sub_kategory";
            System.Data.OleDb.OleDbDataAdapter adapter_b = new System.Data.OleDb.OleDbDataAdapter(command_b, global::Netcode.Properties.Settings.Default.csanConnectionString);

            adapter_b.Fill(topics, "sub_kategory");
            #endregion

            for (int j = 0; j < topics.Tables["sub_kategory"].Rows.Count; j++)
            {
                tv.Nodes[i].Nodes.Add("", topics.Tables["sub_kategory"].Rows[j]["sub_kategory"].ToString(), 1);
                Application.DoEvents();

                #region Заполнение C
                string command_c = "Select * from articles WHERE articles.id_sk = " + topics.Tables["sub_kategory"].Rows[j]["id_sk"].ToString() + " ORDER BY articles";
                System.Data.OleDb.OleDbDataAdapter adapter_c = new System.Data.OleDb.OleDbDataAdapter(command_c, global::Netcode.Properties.Settings.Default.csanConnectionString);

                adapter_c.Fill(topics, "articles");
                #endregion

                for (int k = 0; k < topics.Tables["articles"].Rows.Count; k++)
                {
                    tv.Nodes[i].Nodes[j].Nodes.Add("", topics.Tables["articles"].Rows[k]["articles"].ToString(), 2);
                    lb.Text = "Загружено статей " + col;
                    col++;
                    Application.DoEvents();
                }
                topics.Tables["articles"].Clear();
                adapter_c.Dispose();
            }
            topics.Tables["sub_kategory"].Clear();
            adapter_b.Dispose();
        }
        topics.Tables["kategory"].Clear();
        topics.Dispose();
        adapter_a.Dispose();
        lb.Text = "Все статьи загружены (" + col.ToString() +" шт.)";
    }
}

#endregion



Это сообщение отредактировал(а) Softaz - 9.11.2006, 20:45


--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
Exception
Дата 9.11.2006, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 4525
Регистрация: 26.12.2004

Репутация: 5
Всего: 186



Цитата

Application.DoEvents();


это ещё зачем? Попробуй без него

Добавлено @ 21:01 
Ну и ещё неплохо вызывать SQL в отдельном потоке (если он тормозит).
PM   Вверх
Softaz
Дата 9.11.2006, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 3
Всего: 16




Цитата

это ещё зачем? Попробуй без него

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

Можно, конечно, загружать сначала только корневые ноды, а в обработчике события Expand проверять, загружены ли Child-ноды и, если нет, подгружать к выбранной корневой остальное и т.д. и т.п., но я видел загрузку всего дерева намного быстрей представленной.
Да и организовать тупую загрузку всего дерева на вид проще.


--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
mr.DUDA
Дата 10.11.2006, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 24
Всего: 232



Softaz, рекомендация одна: не добавлять в дерево узлы сразу, т.е. сначала грузить во временную структуру, а потом - всем скопом добавлять в дерево. Проверить справедливость этого очень просто: убрать из кода всё что так или иначе связано с TreeView и добавлять к примеру, в Dictionary. Кроме того, зачем грузить всё сразу ? Если можно в рамках задачи, то намного экономнее подгружать данные по ходу раскрытия узлов дерева (BeforeExpand на то и придуман)... извините за банальность, дерево ведь дерево а не список.


--------------------
user posted image
PM MAIL WWW   Вверх
Softaz
Дата 10.11.2006, 02:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 3
Всего: 16



Мне кажется, что еще одно узкое место - запрос в БД. Вот следующий код загружает около 2500 тыщ нод за 2 секунды. Соответственно, нужно придумать, как быстро сортировать данные.

Код

TreeNode[] tn = new TreeNode[2];
Random rnd = new Random();
for (int i = 0; i < tn.Length; i++)
{
   tn[i] = new TreeNode(rnd.Next(0, 1245678).ToString());
     for (int j = 0; j < 200; j++)
    {
        tn[i].Nodes.Add(rnd.Next(0, 1245678).ToString());
        for (int k = 0; k < 10; k++)
       {
           tn[i].Nodes[j].Nodes.Add(rnd.Next(0, 1245678).ToString());
        }
    }
}
treeView1.Nodes.AddRange(tn);



--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
Softaz
Дата 10.11.2006, 03:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 3
Всего: 16



Так оно и было.
Буду подгружать дерево по BeforeExpand. Это оказывается намного проще.


--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
archimed7592
Дата 10.11.2006, 05:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 3
Всего: 93



Цитата(Softaz @  10.11.2006,  04:16 Найти цитируемый пост)
Буду подгружать дерево по BeforeExpand.
угу. +использовать умное удаление. т. е. 
удалять большие ноды на AfterCollapse и использовать e.Node.Tag для определения загруженна ли ветка.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
mr.DUDA
Дата 10.11.2006, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 24
Всего: 232



Цитата(archimed7592 @  10.11.2006,  04:41 Найти цитируемый пост)
и использовать e.Node.Tag для определения загруженна ли ветка.

Тут похитрее придётся делать: чтобы ветку можно было раскрывать, т.е. чтобы появился "плюсик", нужно добавлять ноду-пустышку (которую мы отличим по ссылке, или по Tag-у), при раскрытии узла в BeforeExpand проверять - есть ли под ним пустышка или нет. Если есть - удалять её и наполнять узлами по запросу БД.

Добавлено @ 09:00 
З.Ы. вопрос вообще говоря, в WinForms


--------------------
user posted image
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Разработка Windows Forms | Следующая тема »


 




[ Время генерации скрипта: 0.0570 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.