|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
Вопрос, собссно, сабж. Пользуясь DataReader уперся в отсутствие использования нескольких ридеров с одним Connection. В некоторых случаях конекшены плодятся просто безобразно. Что делать? Использовать DataSet? Он мне показался несколько громоздким. А надо всего-то заполнить визуальные компоненты информацией из бд. Например для заполнения двухуровнего TreeView надо минимум 2 ридера (т.е. и 2 Конекшена) а если TreeView бесконечной вложенности и использовать обычную рекурсивную процедуру, то DataReader (и соответственно Connection) надо будет рожать на каждом уровне вложенности, т.е. в каждом вызове процедуры. Фигня получается. Или это нормально? Может кто чего подскажет, если уже сталкивался. DataSet использовать не очень хочется еще и потому, что нужно только читать данные, но не редактировать. Да и скорость, которую дает ридер - не лишняя. Спасибо! ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2004, 15:36 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
А можно поподробнее структура таблицы и утрированный пример кода (доступ к БД, заполнение treeView), примерное количество записей? >Пользуясь DataReader уперся в отсутствие использования нескольких ридеров с одним Connection. Да на одно соединение - ОДИН DataReader. Только не понятно в чем заключается проблема с использованием нескольких соединений. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2004, 18:08 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
И мне интересно. Где автор? 2 SA Я смотрю ты "дед" на этой ветке форума. Молодец ! ... |
|||
:
Нравится:
Не нравится:
|
|||
23.03.2004, 18:48 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
to: Sa >Да на одно соединение - ОДИН DataReader. Только не понятно в чем >заключается проблема с использованием нескольких соединений. Проблема заключается в том, что из общих представлений и опыта работы с БД, кажется не логичным (экономичным и пр.) плодить Connection. Ведь каждый открытый конекшен - это (в частном случае) и сетевое соедниение не говоря оресурсах компа. Т.е. вопрос в следующем: НОРМАЛЬНО ЛИ плодить конекшены для ADO, если - нет, что тогда надо использовать : DataSet? Пример кода (хотя, что он даст?): Это процедура заполняющая TreeView из простой рекурсивной таблицы городов/регионов 2-х уровней вложенности. Здесь уже требуется мин 2 конекшена. Это мне и не нравится. Если же на форме десяток комбобоксов и листбоксов, на каждый, получается, надо минимум по 1 конекшену. Это нормально? Или в таких случаях надо в ADO создавать всю схему на стороне клиента с помощью DataSet? Но это ж страшный геморрой!... Не знал, что вырезать и привел целый кусок кода (пардон)... cnnRegion.Open(); // объявлен выше OleDbCommand cmdRegion = cnnRegion.CreateCommand(); cmdRegion.CommandText = "SELECT region_id, region_name FROM t_region WHERE region_code =1 ORDER BY region_name"; OleDbDataReader rdrRegion = cmdRegion.ExecuteReader(); tvState.Nodes.Clear(); int i = 0; OleDbConnection cnnCity = new OleDbConnection ("Provider=Microsoft.Jet.OLEDB.4.0;Password=\"\";User ID=Admin;Data Source=G:\\MSVCPP\\firm_dat.mdb;"); cnnCity.Open(); OleDbCommand cmdCity = cnnCity.CreateCommand(); while (rdrRegion.Read()) { tvState.Nodes.Add(new TreeNode(rdrRegion.GetString(1))); tvState.Nodes .Tag = rdrRegion.GetInt32(0); cmdCity.CommandText = "SELECT region_id, region_name FROM t_region WHERE region_code = " + Convert.ToString(tvState.Nodes.Tag) + " ORDER BY region_name"; OleDbDataReader rdrCity = cmdCity.ExecuteReader(); int j = 0; while (rdrCity.Read()) { tvState.Nodes .Nodes.Add(new TreeNode(rdrCity.GetString(1))); tvState.Nodes.Nodes[j].Tag = rdrCity.GetInt32(0); j++; } rdrCity.Close(); i++; } rdrRegion.Close(); cnnCity.Close(); ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2004, 02:35 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
Да, забыл сказать... Как я понял из литературы, DataReader - это некий аналог Recordset. Такой аналог я и ищу, но как оказалось, для каждого DataReader нужен cвой Connеction (в отличии от ситуации с Recordset). Это меня смущает. (исходя из опыта работы с Delphi, Access/DAO, Oracle/Java кажется диким плодить конекшены для каждого запроса на выборку) Спасибо всем откликнувшимся! ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2004, 02:44 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
DataReader - однонаправленный курсор. Сделан, что-бы быстренько пробежаться по результатам выборки в одну сторону и закрыть и забыть его. Так что как вариант либо заполнить только первый уровень, а когда попытаются открыть любой узел, то его дозаполнить узлами второго уровня (Load on demand), либо перегрузить первый уровень в свои структуры данных (ex. ArrayList) и информацию оттуда использовать для заполнения второго уровня дерева. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2004, 08:44 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
Согласен с Артемом по загрузке данных по требованию. С ADO.NET такой вариант очень эффективно проходит, так как соединение преимущественно повторно используется из пула соединений. Поповоду вашего кода, здесь непонятки, разъясните структуру вашей таблицы, примерные данные из нее, количество записей. Возможно это как раз вариант - когда необходимо нормализовать базу данных. По поводу >плодить конекшены для каждого запроса на выборку. Здесь ничего страшного, главное - открывать соединение как можно позже а закрывать как можно раньше, только закрытое соединения (dispose, close, или в случае с DataReader - CommandBehavior.CloseConnection) возвращается в пул. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2004, 11:04 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
Артем1: ага, спасибо, интересный вариант. Попробую. Sa : с таблицей все нормально. Обычная рекурсивная таблица (ссылка сама на себя). region_id / region_name /region_code 1 Deutschland 1 2 Bayern 1 3 München 2 4 Nürnberg 2 5 Augsburg 2 8 Landshut 2 9 Regensburg 2 10 Berlin 1 11 Berlin 10 С ней все работает. Смущало только наличие второго Connection, или их бесконечного множества в случае многоуровневости (например тематичский справочник). >Здесь ничего страшного, главное - открывать соединение как можно позже а >закрывать как можно раньше, только закрытое соединения (dispose, close, >или в случае с DataReader - CommandBehavior.CloseConnection) возвращается >в пул. Вот меня это и беспокоило. Если это нормальная практика в ADO (в Delphi и в Accesse обычно создавался один Connection, а потом плодились запросы к нему) - тогда все в порядке. Спасибо за помощь! ... |
|||
:
Нравится:
Не нравится:
|
|||
24.03.2004, 17:13 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
Думаю тут совсем не критично скидывать данные в DataSet, или вручную нагружать одним readeroм DataTable, ArrayList ... Но вариант предложенный Артемом считаю лучшим. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.03.2004, 08:13 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
Мои 2 копейки, так же столкнулся с проблемой 1 Connection 1 DataReader вышел из положения так: Создал таблицу и залил в нее данные DataTable MyTable=new DataTable ("ALL_SPRAV"); OracleDataAdapter MyAdapter = new OracleDataAdapter ("select * from Mytree",MyoracleConnection); MyAdapter.Fill (MyTable); а затем заполняю дерево на основе этой таблицы через рекурсию protected void Re(String nn,ref TreeNode MTN) // Рекурсивная функция { String st="kod_parent="+nn; DataRow [] DR = BindingTable.Select (st); TreeNode MTN1; for (int i=0; i<DR.Length;i++ ) { MTN1=new TreeNode() ; MTN1.Text =DR ["NAME"].ToString(); MTN1.Tag =DR["KOD"].ToString(); MTN.Nodes.Add (MTN1); this.Re(DR["KOD"].ToString(),ref MTN1); } } public void Fill(String root) // Мето по "заливке данных" { if (BindingTable!=null) { String st="kod_parent="+root; DataRow [] DR = BindingTable.Select (st); TreeNode MTN1; for (int i=0; i<DR.Length;i++ ) { MTN1=new TreeNode() ; MTN1.Text =DR["NAME"].ToString(); MTN1.Tag =DR["KOD"].ToString(); this.Nodes.Add (MTN1); this.Re(DR["KOD"].ToString(),ref MTN1); } } код вырван из собственного класса унаследованного от TreeView но вообщем принцип должен быть понятен } ... |
|||
:
Нравится:
Не нравится:
|
|||
26.03.2004, 09:15 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
авторСоздал таблицу и залил в нее данные DataTable MyTable=new DataTable ("ALL_SPRAV"); OracleDataAdapter MyAdapter = new OracleDataAdapter ("select * from Mytree",MyoracleConnection); MyAdapter.Fill (MyTable); А если вот в этом самом "select * from Mytree" порядка 100000 записей? Сколько строится дерево? Метод загрузки дерева On Demand, который предложил выше Артем, ИМХО, является лучшим для деревянных структур. Во-первых, он сильно экономит память, поскольку в дереве содержатся только отображаемые ноды, во-вторых сильно снижает нагрузку на БД. Ну и если дополнить загрузку детей при раскрытии нода "убиением" потомков при схлопывании нода - получится самообновляемое дерево (во всяком случае при закрытии-раскрытии нода). Такой подход мы используем уже давно, и он полностью себя оправдал. Полная загрузка дерева годится для малого количества записей. Да и treeview - не самый быстрый контрол :) ... |
|||
:
Нравится:
Не нравится:
|
|||
27.03.2004, 11:54 |
|
Несколько Connection для заполнения TreeView??!
|
|||
---|---|---|---|
#18+
>А если вот в этом самом "select * from Mytree" порядка 100000 записей? Всегда надо исходить из фактов, поэтому я и спрашивал автора: структуру таблицы, количество записей. В Реалии - здесь идет речь о СПРАВОЧНИКЕ городов и регионов, которые совершенно не критично например закинуть в DataSet, Методов решения задачи множество. Поэтому можно выбрать наиболее легкий в программировании вариант. Вариант предложенный артемом просто красивый и универсальный - ИМХО лучший. 2 avg В качестве ОБЩЕГО решения задачи согласен с вами на все 100%. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2004, 09:43 |
|
|
start [/forum/topic.php?fid=17&msg=32457914&tid=1354179]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
36ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
51ms |
get tp. blocked users: |
1ms |
others: | 239ms |
total: | 372ms |
0 / 0 |