заполнение TreeView из БД
От: Max951  
Дата: 22.03.04 02:52
Оценка:
Привет!
1.Пытаюсь реаллизовать алгоритм Nested Sets и заполнить TreeView из БД, но пока толком ничего не получается. Можете привести простой пример заполнения этого дерева из БД(с поиском как-нить разберусь).
2.Ещё также не понятно грузить всё дерево сразу или до какого-то уровня, а потом подгружать по мере необходимости?
Буду благодарен за пример или ссылку.
Спасибо.
Re: заполнение TreeView из БД
От: dertotejunge  
Дата: 22.03.04 06:25
Оценка:
Здравствуйте, Max951, Вы писали:

M>Привет!

M>1.Пытаюсь реаллизовать алгоритм Nested Sets и заполнить TreeView из БД, но пока толком ничего не получается. Можете привести простой пример заполнения этого дерева из БД(с поиском как-нить разберусь).

по поводу заполнения из бд — я делал примерно так:
объявляешь структуру с полями ID, ParentID, TreeNode
сначала пробегаешся по выборке из базы и на ее основе генеряешь вектор(или список) таких структур, т.е. загоняешь туда ID, ParentID, а так же создаешь TreeNode
теперь бежишь по полученному вектору и находя по ParentID родителя текущей ноды запихиваешь ее в него, и т.д., ежели ParentID неопределен, то это будет корневая нода, и тогда ее запихиваешь прямо в контейнер нод дерева.
Я делал так, может кто более рацинальный метод предложит....


M>2.Ещё также не понятно грузить всё дерево сразу или до какого-то уровня, а потом подгружать по мере необходимости?

по поводу подгрузки, например под NN данное дерево все равно будет работать через сервер (т.е. там даже на открытие ноды будет срабатывать постбэк) И еще интересно как ты будешь подгружать по мере необходимости, т.е. ты хочешь сказать дереву, что допустим не надо выполнять постбэк на OnExpand ежели уровень допустим меньше 5, а ежели больше то нужно.... я сомневаюсь что так можно сделать нормальным способом, а не через ...


M>Буду благодарен за пример или ссылку.

M>Спасибо.
Re[2]: заполнение TreeView из БД
От: Gollum Россия  
Дата: 22.03.04 06:36
Оценка:
Здравствуйте, dertotejunge, Вы писали:

D>теперь бежишь по полученному вектору и находя по ParentID родителя текущей ноды запихиваешь ее в него, и т.д., ежели ParentID неопределен, то это будет корневая нода, и тогда ее запихиваешь прямо в контейнер нод дерева.

D>Я делал так, может кто более рацинальный метод предложит....

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

D>по поводу подгрузки, например под NN данное дерево все равно будет работать через сервер (т.е. там даже на открытие ноды будет срабатывать постбэк)


Вот это новость. Это точно? Хотя ведь, NN не поддерживает .htc ?

D> И еще интересно как ты будешь подгружать по мере необходимости, т.е. ты хочешь сказать дереву, что допустим не надо выполнять постбэк на OnExpand ежели уровень допустим меньше 5, а ежели больше то нужно.... я сомневаюсь что так можно сделать нормальным способом, а не через ...


Можно. В XML'е у нод выше пятого уровня заполняешь контент, а у остальных ставишь датасорс — вебсервис, например. При открытии ноды он автоматически будет подтягивать данные с вебсервиса.
По всей Смоленщине нет кокаина — это временный кризис сырья
Eugene Agafonov on the .NET

Re: заполнение TreeView из БД
От: hellraiser Беларусь  
Дата: 22.03.04 07:19
Оценка:
Здравствуйте, Max951, Вы писали:

M>Привет!

M>1.Пытаюсь реаллизовать алгоритм Nested Sets и заполнить TreeView из БД, но пока толком ничего не получается. Можете привести простой пример заполнения этого дерева из БД(с поиском как-нить разберусь).
M>2.Ещё также не понятно грузить всё дерево сразу или до какого-то уровня, а потом подгружать по мере необходимости?
M>Буду благодарен за пример или ссылку.
M>Спасибо.
все выдрано из рабочего проекта, приспособить под себя думаю проблем не будет.
        private TreeNode tree_bind(SqlInt32 id, SqlString title, SqlString navigate_url, SqlBoolean child, TreeNode n)
        {
            n.Text = title.ToString().Trim();
            n.NodeData = id.ToString();

            if (!navigate_page.Equals(""))
                if (navigate_url.IsNull) n.NavigateUrl = String.Format("{0}?nid={1}", navigate_page, id.ToString());
                    else n.NavigateUrl = navigate_url.ToString();

            if (child.IsTrue)
            {
                SqlConnection _connection = new SqlConnection(((string)(configurationAppSettings.GetValue("main_sqlConnection_ru.ConnectionString", typeof(string)))));
                SqlCommand _command = new SqlCommand (String.Format("select id, title, child, navigate_url from tree where root_node_id = {0} order by child desc, title", id), _connection);

                try
                {
                    _command.Connection.Open();

                    SqlDataReader _reader = _command.ExecuteReader();

                    TreeNode _node = new TreeNode();

                    while (_reader.Read())
                    {
                        n.Nodes.Add(tree_bind(_reader.GetSqlInt32(0), _reader.GetSqlString(1), _reader.GetSqlString(3), _reader.GetSqlBoolean(2), new TreeNode()));
                    }

                    _reader.Close();
                }
                finally
                {
                    _command.Connection.Close();
                    _command.Dispose();
                }
            }

            return n;
        }

заполнение вызываеш так:
            protected Microsoft.Web.UI.WebControls.TreeView tv;
            .....
            tv.Nodes.Clear();
            
            SqlConnection _connection = new SqlConnection(((string)(configurationAppSettings.GetValue("main_sqlConnection_ru.ConnectionString", typeof(string)))));
            SqlCommand _command = new SqlCommand(String.Format("SELECT id, title, child, navigate_url FROM tree WHERE (root_n" +
                "ode_id {0}) ORDER BY child DESC", _root_node_id.Equals(int.MinValue) ? "is null" : String.Format("={0}", _root_node_id)), _connection);

            try
            {
                _connection.Open();

                SqlDataReader _tree_reader = _command.ExecuteReader();

                while (_tree_reader.Read())
                {
                    tv.Nodes.Add(tree_bind(_tree_reader.GetSqlInt32(0), _tree_reader.GetSqlString(1), _tree_reader.GetSqlString(3), _tree_reader.GetSqlBoolean(2), new TreeNode()));
                }

                _tree_reader.Close();
            }
            finally
            {
                _connection.Close();
            }

где _root_node_id — id ветки с которой нужно начать посторение. считается что есть также и суперрутовые ветки для которых поле root_node_id всегда равно null
также в довесок привожу sql скрипт дерева на базе ms sql 2000
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[exists_child]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[exists_child]
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS OFF 
GO

CREATE FUNCTION exists_child (@root_id int)  
RETURNS bit AS  
BEGIN
   declare @b bit

   if exists (select id from tree where root_node_id=@root_id)
      set @b = 1
   else
      set @b = 0

   return @b
END

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO


if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[FK_characteristic_value_tree]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [dbo].[characteristic_value] DROP CONSTRAINT FK_characteristic_value_tree
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[FK_tree_nodes_images_tree]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [dbo].[tree_nodes_images] DROP CONSTRAINT FK_tree_nodes_images_tree
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[delete_tree_node]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
drop trigger [dbo].[delete_tree_node]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[tree]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[tree]
GO

CREATE TABLE [dbo].[tree] (
    [id] [int] IDENTITY (1, 1) NOT NULL ,
    [title] [varchar] (150) COLLATE Cyrillic_General_CI_AS NOT NULL ,
    [root_node_id] [int] NULL ,
    [child] AS ([dbo].[exists_child]([id])) ,
    [description] [text] COLLATE Cyrillic_General_CI_AS NULL ,
    [navigate_url] [varchar] (250) COLLATE Cyrillic_General_CI_AS NULL 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[tree] WITH NOCHECK ADD 
    CONSTRAINT [PK_tree] PRIMARY KEY  CLUSTERED 
    (
        [id]
    )  ON [PRIMARY] 
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE trigger delete_tree_node on dbo.tree
for delete 
as
if exists(select tree.ID from tree, deleted D where tree.root_node_id=D.ID)
delete from tree
from tree, deleted D where tree.root_node_id=D.ID

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO
Re[2]: заполнение TreeView из БД
От: Gollum Россия  
Дата: 22.03.04 07:36
Оценка:
Здравствуйте, hellraiser, Вы писали:

H>все выдрано из рабочего проекта, приспособить под себя думаю проблем не будет.


а) Параметры к SQL-командам лучше добавлять с использованием SQLParameter, а не String.Format
б) Не надо столько раз открывать и закрывать соединение, хоть оно и берется из пула. Достаточно один раз открыть и один раз закрыть.
в) Можно подумать о рефакторинге — при внесении изменений в такой код будет масса проблем.
Скорость перебора паролей прямо пропорциональна квадрату температуры утюга...
Eugene Agafonov on the .NET

Re[3]: заполнение TreeView из БД
От: hellraiser Беларусь  
Дата: 22.03.04 08:09
Оценка:
Здравствуйте, Gollum, Вы писали:

G>Здравствуйте, hellraiser, Вы писали:


H>>все выдрано из рабочего проекта, приспособить под себя думаю проблем не будет.


G>а) Параметры к SQL-командам лучше добавлять с использованием SQLParameter, а не String.Format

с этим готов согласится.
G>б) Не надо столько раз открывать и закрывать соединение, хоть оно и берется из пула. Достаточно один раз открыть и один раз закрыть.
я при чтении использую sqlreader а он производит только линейное чтение, поэтому если использовать только один конекшен, то при создании следуещего ридера и попытке им воспользоваться выскочит ексепшен, о том что нельзя позиционировать для этого соеденинения. помоему так, хотя я уже точно непомню, но какаято трабла с использованием этого была.
G>в) Можно подумать о рефакторинге — при внесении изменений в такой код будет масса проблем.
например? я негарантирую на то что это идеальный код, возможны еще более лучшее прграммирование заполнения дерева, могу еще как один из способов считать все дерево в датасет и затем заполнять его следующим способом, тогда вообщше не нужно будет создавать конекшен поновой. вот напрмер так:
        private TreeNode tree_bind(int id, string title, bool child, TreeNode n)
        {
            n.Text = title.ToString().Trim();
      n.NodeData = id.ToString();

            if (child == true)
            {
                using(DataView _dv = new DataView(ds_tree1.Tables["tree"], String.Format("root_node_id = {0}", id), "child desc, title", DataViewRowState.CurrentRows))
                {
                    for(int i = 0; i < _dv.Count; i++)
                    {
                        n.Nodes.Add(tree_bind((int)_dv[i]["id"], (string)_dv[i]["title"], (bool)_dv[i]["child"], new TreeNode()));
                    }
                }
            }
            return n;
        }

заполняем так тогда:
            tv.Nodes.Clear();

            using(DataView _dv = new DataView(ds_tree1.Tables["tree"], "root_node_id is null", "child desc, title", DataViewRowState.CurrentRows))
            {
                for(int i = 0; i < _dv.Count; i++)
                {
                    tv.Nodes.Add(tree_bind((int)_dv[i]["id"], (string)_dv[i]["title"], (bool)_dv[i]["child"], new TreeNode()));
                }
            }
Re[3]: заполнение TreeView из БД
От: dertotejunge  
Дата: 22.03.04 08:14
Оценка:
Здравствуйте, Gollum, Вы писали:

D>>по поводу подгрузки, например под NN данное дерево все равно будет работать через сервер (т.е. там даже на открытие ноды будет срабатывать постбэк)


G>Вот это новость. Это точно? Хотя ведь, NN не поддерживает .htc ?


да это так... а иногда у него вааще крышу срывает (у дерева), т.е. оно вааще переастает работать, это случается када допускаешь какуюнить ошибку разметки страницы, на которую експлорер забивает а NN не может, ну а вааще конечно MS и не декларировал что эта штука будет работать под NN, хотя работает, но иногда не совсем так как хотелось бы.... (
Re[4]: заполнение TreeView из БД
От: Gollum Россия  
Дата: 22.03.04 08:27
Оценка:
Здравствуйте, dertotejunge, Вы писали:

D>да это так... а иногда у него вааще крышу срывает (у дерева), т.е. оно вааще переастает работать, это случается када допускаешь какуюнить ошибку разметки страницы, на которую експлорер забивает а NN не может, ну а вааще конечно MS и не декларировал что эта штука будет работать под NN, хотя работает, но иногда не совсем так как хотелось бы.... (


Дык называется то оно Internet Explorer Web Controls
В следующем аспнете есть встроенный тривью, так что...
Моя смерть ездит в черной машине с голубым огоньком
Eugene Agafonov on the .NET

Re[5]: заполнение TreeView из БД
От: hellraiser Беларусь  
Дата: 22.03.04 08:39
Оценка:
Здравствуйте, Gollum, Вы писали:

G>Здравствуйте, dertotejunge, Вы писали:


D>>да это так... а иногда у него вааще крышу срывает (у дерева), т.е. оно вааще переастает работать, это случается када допускаешь какуюнить ошибку разметки страницы, на которую експлорер забивает а NN не может, ну а вааще конечно MS и не декларировал что эта штука будет работать под NN, хотя работает, но иногда не совсем так как хотелось бы.... (


G>Дык называется то оно Internet Explorer Web Controls

G>В следующем аспнете есть встроенный тривью, так что...
а когда следующий asp.net? хочу.
Re[4]: заполнение TreeView из БД
От: Gollum Россия  
Дата: 22.03.04 08:55
Оценка:
Здравствуйте, hellraiser, Вы писали:

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


Если ридер закрывать, траблов нет Только что сам проверил.

H>считать все дерево в датасет и затем заполнять его следующим способом, тогда вообщше не нужно будет создавать конекшен поновой. вот напрмер так:


Вообще мне нравится такой вариант — в слое данных брать датасет и отдавать в бизнес-логику. В бизнес-логике из датасета делать XML и байндить к нему дерево. но тут конечно все зависит от масштабов задачки, размеров дерева и т.п.
Ihesu who hath wonders sore, grants us the blyss of heathen
Eugene Agafonov on the .NET

Re[6]: заполнение TreeView из БД
От: Gollum Россия  
Дата: 22.03.04 08:55
Оценка:
Здравствуйте, hellraiser, Вы писали:

G>>В следующем аспнете есть встроенный тривью, так что...

H>а когда следующий asp.net? хочу.

По слухам альфа 2 будет уже совсем скоро, публичная бета — в мае.
Ihesu who hath wonders sore, grants us the blyss of heathen
Eugene Agafonov on the .NET

Re[5]: заполнение TreeView из БД
От: hellraiser Беларусь  
Дата: 22.03.04 09:24
Оценка:
Здравствуйте, Gollum, Вы писали:

H>>считать все дерево в датасет и затем заполнять его следующим способом, тогда вообщше не нужно будет создавать конекшен поновой. вот напрмер так:


G>Вообще мне нравится такой вариант — в слое данных брать датасет и отдавать в бизнес-логику. В бизнес-логике из датасета делать XML и байндить к нему дерево. но тут конечно все зависит от масштабов задачки, размеров дерева и т.п.

а вообще какой вид должен иметь xml файл, для того чтобы подать его на вход контрола
Re[6]: заполнение TreeView из БД
От: Gollum Россия  
Дата: 22.03.04 09:30
Оценка:
Здравствуйте, hellraiser, Вы писали:

H>а вообще какой вид должен иметь xml файл, для того чтобы подать его на вход контрола


Динамическое формирование узлов TreeView
Автор: Stewe
Дата: 03.10.03
Товариши офицеры, вот вы сейчас ничего не слушаете, а потом придет время — вы протона от электрона отличить не сможете!
Eugene Agafonov on the .NET

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.