- PR -

TreeViewの追加方法について教えて下さいA

投稿者投稿内容
Kimi
会議室デビュー日: 2008/10/03
投稿数: 7
投稿日時: 2008-10-05 15:00
何度も申し訳ありません。
昨晩、テストデータ(下記の小ねじデータのみ)で出来たつもりでしたが、テストデータを下記のように「大ネジ」データを増やしてやったところ、次のような流れで処理が終わってしまいました。

【処理の流れを追ってみました(○数字は下記のソースの番号です)】
@parent:"-" →「部品名1」を読込み
 @parent:"nameA.aspx" →「小ねじ」を読込み
  @parent:"nameB.aspx" →「5mm*10mm」を読込み
   @parent:"n1.aspx" →「5mm*15mm」を読込み
   B →"n1.aspx"レコードはparentにありません
   D
  A「5mm*10mm」をTreeViewに書き込み、再帰から戻ってきた
 A「小ねじ」をTreeViewに書き込み、再帰から戻ってきた
A「部品名1」をTreeViewに書き込み、再帰から戻ってきた
C次のレコードを読もうとして、次のエラーメッセージが表示されました
 『データリーダが閉じているときに、無効な操作Readをしようとしました』
D

これで処理が終了して、
■部品名1
└小ねじ
 └5mm*10mm
この形でTreeViewが作成されました。


【テストデータ】
url     |title   |parent
------------+----------+-------
default.aspx|部品名1 |-
nameA.aspx |小ねじ  |Default.aspx
ne1.aspx  |5mm*10mm |nameA.aspx
ne2.aspx  |5mm*15mm |nameA.aspx
nameB.aspx |大ねじ  |Default.aspx
ne3.aspx  |10mm*100mm|nameB.aspx
   :
   :

【本来期待したい形】
■部品名1
├小ねじ
|├5mm*10mm
|└5mm*15mm
├大ねじ
|├10mm*100mm
   :
   :

【実行したソースです】
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
  If IsPostBack = False Then
    Me.CreateNode("-", tree.Nodes)
  End If
End Sub

@ Private Sub CreateNode(ByVal pParent As String, ByVal nodes As TreeNodeCollection)
  COMM = "SELECT * FROM t_zaiko WHERE parent = '" & pParent & "'"
  Using connect As New SqlConnection(dbConnectString)
  Dim SQLcom As New SqlCommand(COMM, connect)
    Try
    connect.Open()
    COMMr = SQLcom.ExecuteReader
    While COMMr.Read = True
      Dim node As New TreeNode()
      node.NavigateUrl = COMMr("url")
      node.Text = COMMr("title")
      node.Value = COMMr("url")
      CreateNode(COMMr("url"), node.ChildNodes)
A:再帰から戻ってきた
      nodes.Add(node)
    End While
B:レコードなし
    Catch ex As Exception
C:エラー
    End Try
  End Using
D
End Sub


最後に再帰から戻ってきて、次のレコードを読もうとした時に、一番最初のデータリーダが閉じられてしまっているようです。
クローズしていないので何故クローズ状態になるのでしょうか?


また、小ノードを追加するために再帰的に実行していますが、再帰した時は@から実行されるようですので、同じデータリーダが存在することになると思います(違いますか?)。
これは大丈夫なのでしょうか?

どなたか、ご教授して頂ける方がおられましたら、よろしくお願い致します。
ぴあちゃん
ぬし
会議室デビュー日: 2008/02/07
投稿数: 287
投稿日時: 2008-10-06 19:17
ステップ実行してどこでエラーが出ているのか確認して下さい。

エラーメッセージはそのまんま、
「データリーダが閉じているときに、無効な操作Readをしようとしました」
です。
これをどこかでやっています。たぶん。

Java で悪いのですが、VB.NET に毛が生えたようなイメージで捉えて
もらえるとうれしいですねw

再帰処理部分は応用できるでしょう。

処理結果
■在庫管理■
 ■ネジ
  ▼10mm
  ▼15mm
  ▼20mm
  ■逆ネジ
   ▼10mm
   ▼15mm
   ▼20mm
 ■ナット
 ■ワッシャ
 ■リベット


データベースに登録してあるデータ(XML 形式)
コード:

<?xml version="1.0" encoding="Shift_JIS" ?>

<db name="ZAIKOTBL">
<node name="■ネジ" id="0" pid="" />
<node name="▼10mm" id="1" pid="0" />
<node name="▼15mm" id="2" pid="0" />
<node name="▼20mm" id="3" pid="0" />
<node name="■逆ネジ" id="4" pid="0" />
<node name="▼10mm" id="5" pid="4" />
<node name="▼15mm" id="6" pid="4" />
<node name="▼20mm" id="7" pid="4" />
<node name="■ナット" id="8" pid="" />
<node name="■ワッシャ" id="9" pid="" />
<node name="■リベット" id="10" pid="" />
</db>



DataSet のエミュレータ?
コード:

/*
* 作成日: 2008/10/06
*/
package jp.co.test;

import org.xml.sax.*;
import javax.xml.parsers.*;
import java.io.*;
import java.util.*;

import org.xml.sax.helpers.DefaultHandler;

public class MyDataSet extends DefaultHandler {

Map map = new HashMap();
private String currentDbName;
MyDataRowCollection mrc;

public MyDataSet(String xmlFile) throws IOException, SAXException, ParserConfigurationException {
SAXParserFactory sax = SAXParserFactory.newInstance();
SAXParser parser = sax.newSAXParser();
parser.parse(new File(xmlFile), this);
}

public void startElement(String url, String localName, String qName, Attributes attr) {
if (qName.equals("db")) {
currentDbName = attr.getValue("name");
mrc = new MyDataRowCollection();
map.put(currentDbName, mrc);
}
if (qName.equals("node")) {
mrc.addRow(new MyDataRow(
attr.getValue("name"),
attr.getValue("id"),
attr.getValue("pid")));
}
}

public MyDataRowCollection getDataSet(String dbName) {
return (MyDataRowCollection)map.get(dbName);
}

public static void main(String[] args) {

try {
MyDataSet m = new MyDataSet("TEST.xml");

MyDataRowCollection mrc = m.getDataSet("ZAIKOTBL");

Iterator it = mrc.listIterator();
while (it.hasNext()) {
MyDataRow mr = (MyDataRow)it.next();
System.out.println(mr);
}
}
catch (Exception we) {
we.printStackTrace();
}
}
}



DataRowCollection のエミュレータ?
コード:

/*
*/
package jp.co.test;

import java.util.*;
/**
*/
public class MyDataRowCollection {
List list = new ArrayList();

public void addRow(MyDataRow row) {
list.add(row);
}

public MyDataRow getRow(int index) {
return (MyDataRow)list.get(index);
}

public MyDataRow[] getPids(String pid) { //same pid コレクション
List ls = new ArrayList();
for (int i=0;i < list.size();i++) {
MyDataRow r = getRow(i);
if (r.getPid().equals(pid)) ls.add(r);
}
return (MyDataRow[])ls.toArray(new MyDataRow[ls.size()]);
}

public Iterator listIterator() {
return list.iterator();
}

}




DataRow のエミュレータ?(かなり違うかも)
コード:

/*
* 作成日: 2008/10/06
*/
package jp.co.test;

/**
*/
public class MyDataRow {

private String id;
private String pid;
private String name;
public MyDataRow(String name, String id, String pid) {
setId(id);
setPid(pid);
setName(name);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String toString() {
StringBuffer sb = new StringBuffer();

sb.append("<node name='").append(name).append("' id='");
sb.append(id).append("' pid='").append(pid).append("' />");

return sb.toString();
}
}




TreeView クラスのエミュレータ
コード:

/*
* 作成日: 2008/10/06
*/
package jp.co.test;

import java.util.*;

public class TreeView {


public class TreeNode {
String name;
List childNodes = new ArrayList(); //of TreeNode

public String getName() {
return this.name;
}
public TreeNode(String name) {
this.name = name;
}
public void add(TreeNode node) {
childNodes.add(node);
}
public boolean hasChild() {
return childNodes.size() > 0;
}
public int count() {
return childNodes.size();
}
public Iterator listIterator() {
return childNodes.iterator();
}
}

public static void main(String[] args) {

TreeView tv = new TreeView();

TreeNode root = tv.new TreeNode("■在庫管理■");

tv.createTree(root, "");

tv.showTreeView(root, 0);

}

public void createTree(TreeNode root, String pid) {

try {
MyDataSet m = new MyDataSet("TEST.xml");

MyDataRowCollection mrc = m.getDataSet("ZAIKOTBL");

MyDataRow[] rows = mrc.getPids(pid);

for (int i=0;i < rows.length;i++) {
MyDataRow row = rows[i];

TreeNode node = new TreeNode(row.getName());

createTree(node, row.getId());

root.add(node);

}

}
catch (Exception we) {
we.printStackTrace();
}
}

public void showTreeView(TreeNode root, int indent) {
Iterator it = root.listIterator();
showTreeNode(root, indent++);
while (it.hasNext()) {
TreeNode tr = (TreeNode)it.next();
showTreeView(tr, indent);
}
}

public void showTreeNode(TreeNode node, int indent) {
indent = indent * 2;
String indents = " ";

System.out.println(
indents.substring(indents.length() - indent) +
node.getName()
);

}
}




とりあえず、3つくらい前のレスで載せた手順通りに組みまして
正常に動作することは確認できました。

ですので、後はあなたの書き方に問題があるとしか言えません。
たぶん、前に開いたコネクションが勝手に閉じられてしまうという
のはDBのコネクション数が絡んでくる話かと思います。
通常コネクションは1つらしいのでこれを増やすか、データセット
取得したらとりあえずコネクションを閉じる、とか工夫したら
いけるんじゃないかと想像しています。

※しかしなんで TreeNodeCollection なんて使うんです?
じゃんぬねっとさんが言っているように、TreeNode は自身に
子供のコレクションを持っているのでこいつをそのまんま渡せば
済むと思うんだけど。

Javaでごめんなさい、でもやってることは同じです。




# getDataSet ってやっといて返すのはコレクション、なんじゃそりゃ
# な意味不明なメソッドですね。頭こんがらがっています;;




[ メッセージ編集済み 編集者: ぴあちゃん 編集日時 2008-10-06 19:27 ]

スキルアップ/キャリアアップ(JOB@IT)