C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: ADO.NetからXMLを使う方法


(過去ログ 30 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■14263 / inTopicNo.1)  ADO.NetからXMLを使う方法
  
□投稿者/ ふるふる (1回)-(2008/02/14(Thu) 11:12:22)

分類:[XML] 

最近、VB.Net(2003)をはじめました。

INIファイルの代わりにXMLを使おうとして、ACCESSでテーブルを作ってRecordsetの永続化を使い、XMLファイルにしました。Datasetを使ってXMLを取り込みましたが、そこから必要な行を選択する方法がわかりません。
XMLは以下のようになっています。

<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
	xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
	xmlns:rs='urn:schemas-microsoft-com:rowset'
	xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
	<s:ElementType name='row' content='eltOnly'>
		<s:AttributeType name='Environ' rs:number='1' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
			<s:datatype dt:type='string' dt:maxLength='255'/>
		</s:AttributeType>
		<s:AttributeType name='Machine' rs:number='2' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
			<s:datatype dt:type='string' dt:maxLength='255'/>
		</s:AttributeType>
		<s:AttributeType name='MyPath' rs:number='3' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
			<s:datatype dt:type='string' dt:maxLength='255'/>
		</s:AttributeType>
		<s:AttributeType name='DBServer' rs:number='4' rs:nullable='true' rs:maydefer='true' rs:writeunknown='true'>
			<s:datatype dt:type='string' dt:maxLength='255'/>
		</s:AttributeType>
		<s:extends type='rs:rowbase'/>
	</s:ElementType>
</s:Schema>
<rs:data>
	<z:row Environ='Development' Machine='hogehage' MyPath='DEV' DBServer='hogehage'/>
	<z:row Environ='Testing' Machine='hogehage' MyPath='TEST' DBServer='hogehage'/>
	<z:row Environ='Production' Machine='hoge' MyPath='APPL' DBServer='hoge'/>
	<z:row Environ='QA' Machine='hogehage' MyPath='APPL' DBServer='hogehage\QA'/>
</rs:data>
</xml>


プログラム自身のパスとPC名でDBServer(実際はインスタンス名)を取得して、SQLServer2000に接続しようとしています。このプログラムはサーバ上で動くものです。
本来なら サーバのPC名=インスタンス名 としてどのサーバ上にプログラムがあっても関係なく動くようにするものだと思いますが、諸般の事情(開発サーバが急遽テストサーバになってしまってインスタンス名を変えられない)でそうはなっていないので、外部ファイルで環境の違いを吸収しようとしています。

現在は以下のように1行ずつチェックしていますが本来の方法ではないと思います。

Dim rXML As New Data.DataSet
Dim sv As String
rXML.ReadXml(sPath & "\environ.xml") 'sPathは.exeのフルパス
Dim tbl As DataTable
tbl = rXML.Tables(1)
For Each wRow In tbl.Rows
 If UCase(wRow.Item(1)) = UCase(sServer) Then
  If InStr(UCase(sPath), UCase(wRow(2))) Then
    sv = wRow.Item(3)
  End If
 End If
 Console.WriteLine(wRow.Item(0) & "," & wRow.Item(1) & "," & wRow.Item(2) & "," & wRow.Item(3))
Next

ご教示いただければ幸いです。


引用返信 編集キー/
■14270 / inTopicNo.2)  Re[1]: ADO.NetからXMLを使う方法
□投稿者/ 魔界の仮面弁士 (619回)-(2008/02/14(Thu) 12:02:54)
No14263 (ふるふる さん) に返信
> INIファイルの代わりにXMLを使おうとして、ACCESSでテーブルを作ってRecordsetの永続化を使い、
> XMLファイルにしました。Datasetを使ってXMLを取り込みましたが、そこから必要な行を
> 選択する方法がわかりません。

たとえば、こうかな。

Dim dataTable1 As New DataTable()
Using OleDbDataAdapter1 As New OleDb.OleDbDataAdapter()
    Dim rs As Object = CreateObject("ADODB.Recordset")
    rs.Open("C:\sample.xml")
    OleDbDataAdapter1.Fill(dataTable1, rs)
    rs.Close()
    If Marshal.IsComObject(rs) Then
        Marshal.ReleaseComObject(rs)
    End If
End Using

引用返信 編集キー/
■14273 / inTopicNo.3)  Re[2]: ADO.NetからXMLを使う方法
□投稿者/ やじゅ (158回)-(2008/02/14(Thu) 12:22:49)
> ■No14263 (ふるふる さん) に返信
>現在は以下のように1行ずつチェックしていますが本来の方法ではないと思います。
>

質問の意図がいまいち掴めなかったのですが、1行ずつチェックが嫌なら
DataView.RowFilterあたりで抽出すればいいのかなと思いました。
引用返信 編集キー/
■14274 / inTopicNo.4)  Re[2]: ADO.NetからXMLを使う方法
□投稿者/ ふるふる (2回)-(2008/02/14(Thu) 13:03:49)
回答ありがとうございます。
ADODBを使うのも手ですね。
この場合、OleDbDataAdapter1を使わなくても、
rs.Fiter = "条件"
rs.Fields("サーバ名").Value
でとってくればいいですね。.NetからADODBを使うのはあまりよくないような気がしたんですが、
以前の技術を使えて楽は楽ですね。

テーブルをXML化した場合はADOの技術のほうがいいんでしょうか...



No14270 (魔界の仮面弁士 さん) に返信
> ■No14263 (ふるふる さん) に返信
>>INIファイルの代わりにXMLを使おうとして、ACCESSでテーブルを作ってRecordsetの永続化を使い、
>>XMLファイルにしました。Datasetを使ってXMLを取り込みましたが、そこから必要な行を
>>選択する方法がわかりません。
>
> たとえば、こうかな。
>
> Dim dataTable1 As New DataTable()
> Using OleDbDataAdapter1 As New OleDb.OleDbDataAdapter()
> Dim rs As Object = CreateObject("ADODB.Recordset")
> rs.Open("C:\sample.xml")
> OleDbDataAdapter1.Fill(dataTable1, rs)
> rs.Close()
> If Marshal.IsComObject(rs) Then
> Marshal.ReleaseComObject(rs)
> End If
> End Using
引用返信 編集キー/
■14277 / inTopicNo.5)  Re[3]: ADO.NetからXMLを使う方法
□投稿者/ ふるふる (3回)-(2008/02/14(Thu) 13:12:00)
No14273 (やじゅ さん) に返信
>>■No14263 (ふるふる さん) に返信
> >現在は以下のように1行ずつチェックしていますが本来の方法ではないと思います。
>>
>
> 質問の意図がいまいち掴めなかったのですが、1行ずつチェックが嫌なら
> DataView.RowFilterあたりで抽出すればいいのかなと思いました。

.Netにどういうクラスがあるのかよくわからないので、DataViewのようなキーワードをいただけると
助かります。

Dim rXML As New Data.DataSet
rXML.ReadXml(sPath & "\environ.xml")
Dim wView As New DataView(rXML.Tables(1))
wView.RowFilter = "Machine='hogehage' and MyPath='TEST'"
Console.WriteLine(wView.Item(0).Item(3))
でほしい情報が取れました。

ありがとうございました。
解決済み
引用返信 編集キー/
■14278 / inTopicNo.6)  Re[3]: ADO.NetからXMLを使う方法
□投稿者/ 魔界の仮面弁士 (620回)-(2008/02/14(Thu) 14:01:22)
No14274 (ふるふる さん) に返信
> この場合、OleDbDataAdapter1を使わなくても、
> rs.Fiter = "条件"
> rs.Fields("サーバ名").Value
> でとってくればいいですね。

いいえ。それは止めておくべきでしょう。

絞り込みが必要なら、DataView なり BindingSource なりを使えば良いのですから、
先に書いたように、DataTable に受けて、DataTable 側から読み取るようにしてください。


どうしても ADODB だけでやるのであれば、せめて
 name = rs.Fields("DBServer").Value
ではなく、
 name = rs.Collect("DBServer")
の構文を使うことをお薦めします。


Fields 経由での取得を行うとなると、VB.NET においては
 Fs = rs.Fields
 F = Fs("DBServer")
 name = F.Value
 If Marshal.IsComObject(F) Then Marshal.ReleaseComObject(F)
 If Marshal.IsComObject(Fs) Then Marshal.ReleaseComObject(Fs)
のように、Fields コレクションを解放する必要がある(※)ため、コードが煩雑になってしまいます。


(※) ADODB の PIA を参照設定している場合、Fields は COM ではないため、解放不要です。
 しかし、Visual Studio によって自動生成された IA を参照設定している場合や レイトバインド時は、解放処理が必須となります。
 (PIA を使ったとしても、Recordset や Connection は ReleaseComObject が必要ですが)


> .NetからADODBを使うのはあまりよくないような気がしたんですが、
そのとおり、多用は避けるべきでしょう。
実際、負荷の高い状況での利用には適さないようですし。

http://support.microsoft.com/kb/910696/en-us
http://support.microsoft.com/kb/321415/ja


> テーブルをXML化した場合はADOの技術のほうがいいんでしょうか...
もちろん、ふるふるさんが最初に提示されたように、
 dataSet1.ReadXml("environ.xml")
 name = dataSet1.Tables("row").Rows(0)("DBServer")
のように読み取る事は可能ですが、この方法だと、row テーブルの列がすべて String 型になってしまいますし、
主キー情報なども保持されません。(今回は、すべての列がテキストなので、たまたま問題が無かっただけで)

environ.xml の内容をキチンと解析して、型情報などを維持した DataSet/DataTable を
組み立てるには、今回の方法を用いた方が楽である、という事です。



もし、Recordset を使わず、かつ、元データの型情報なども維持させたいのであれば、
XSLT などを用いて、元の XML データを下記の形式に加工しておくという手もあります。

これならば、dataSet1.ReadXML するだけで、型情報なども維持されますよ。


<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true"
     msdata:MainDataTable="environ" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="environ">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Environ" type="xs:string" minOccurs="0" />
                <xs:element name="Machine" type="xs:string" minOccurs="0" />
                <xs:element name="MyPath" type="xs:string" minOccurs="0" />
                <xs:element name="DBServer" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <environ>
    <Environ>Development</Environ>
    <Machine>hogehage</Machine>
    <MyPath>DEV</MyPath>
    <DBServer>hogehage</DBServer>
  </environ>
  <environ>
    <Environ>Testing</Environ>
    <Machine>hogehage</Machine>
    <MyPath>TEST</MyPath>
    <DBServer>hogehage</DBServer>
  </environ>
  <environ>
    <Environ>Production</Environ>
    <Machine>hoge</Machine>
    <MyPath>APPL</MyPath>
    <DBServer>hoge</DBServer>
  </environ>
  <environ>
    <Environ>QA</Environ>
    <Machine>hogehage</Machine>
    <MyPath>APPL</MyPath>
    <DBServer>hogehage\QA</DBServer>
  </environ>
</NewDataSet>

引用返信 編集キー/
■14283 / inTopicNo.7)  Re[4]: ADO.NetからXMLを使う方法
□投稿者/ ふるふる (4回)-(2008/02/14(Thu) 14:53:25)
更なる情報ありがとうございます。

実はXMLファイルを作るときに、Access2003でテーブルを作成して、最初、Exportを使ってXMLを
吐き出しました。そのときに出力する情報として「データのスキーマ(XSD)」もチェックして吐き出したら、
魔界の仮面弁士 さん提示のXMLと同じようになってました。主キー情報も残ってるし。
ただ、その後Excel側からRecordsetを使ってOpen するときに、
実行時エラー3709
「The connection cannot be used to perform this operation. It is either closed or invalid in this context.」
がでてしまい、それならAccessのVBAでRecordsetを使ってSaveしておけばOpenできるだろう、ということで
RecordsetのSaveメソッドでXMLを作成しました。案の定、Openはできたのですが、主キー情報などは無くなってました。
今回は大丈夫ですが、インタフェース処理などでXMLを使ってデータをやり取りするときには問題になりそうです。
いまのところCSVを使うばかりでXMLは使ってませんが。

RecordsetでFilterを使うような処理を.NetでするときはDataViewを使いましょう、という理解でいいでしょうか。



No14278 (魔界の仮面弁士 さん) に返信
> ■No14274 (ふるふる さん) に返信
>>この場合、OleDbDataAdapter1を使わなくても、
>>rs.Fiter = "条件"
>>rs.Fields("サーバ名").Value
>>でとってくればいいですね。
>
> いいえ。それは止めておくべきでしょう。
>
> 絞り込みが必要なら、DataView なり BindingSource なりを使えば良いのですから、
> 先に書いたように、DataTable に受けて、DataTable 側から読み取るようにしてください。
>
>
> どうしても ADODB だけでやるのであれば、せめて
>  name = rs.Fields("DBServer").Value
> ではなく、
>  name = rs.Collect("DBServer")
> の構文を使うことをお薦めします。
>
>
> Fields 経由での取得を行うとなると、VB.NET においては
>  Fs = rs.Fields
>  F = Fs("DBServer")
>  name = F.Value
>  If Marshal.IsComObject(F) Then Marshal.ReleaseComObject(F)
>  If Marshal.IsComObject(Fs) Then Marshal.ReleaseComObject(Fs)
> のように、Fields コレクションを解放する必要がある(※)ため、コードが煩雑になってしまいます。
>
>
> (※) ADODB の PIA を参照設定している場合、Fields は COM ではないため、解放不要です。
>  しかし、Visual Studio によって自動生成された IA を参照設定している場合や レイトバインド時は、解放処理が必須となります。
>  (PIA を使ったとしても、Recordset や Connection は ReleaseComObject が必要ですが)
>
>
>>.NetからADODBを使うのはあまりよくないような気がしたんですが、
> そのとおり、多用は避けるべきでしょう。
> 実際、負荷の高い状況での利用には適さないようですし。
>
> http://support.microsoft.com/kb/910696/en-us
> http://support.microsoft.com/kb/321415/ja
>
>
>>テーブルをXML化した場合はADOの技術のほうがいいんでしょうか...
> もちろん、ふるふるさんが最初に提示されたように、
>  dataSet1.ReadXml("environ.xml")
>  name = dataSet1.Tables("row").Rows(0)("DBServer")
> のように読み取る事は可能ですが、この方法だと、row テーブルの列がすべて String 型になってしまいますし、
> 主キー情報なども保持されません。(今回は、すべての列がテキストなので、たまたま問題が無かっただけで)
>
> environ.xml の内容をキチンと解析して、型情報などを維持した DataSet/DataTable を
> 組み立てるには、今回の方法を用いた方が楽である、という事です。
>
>
>
> もし、Recordset を使わず、かつ、元データの型情報なども維持させたいのであれば、
> XSLT などを用いて、元の XML データを下記の形式に加工しておくという手もあります。
>
> これならば、dataSet1.ReadXML するだけで、型情報なども維持されますよ。
>
>
> <?xml version="1.0" standalone="yes"?>
> <NewDataSet>
> <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema"
> xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
> <xs:element name="NewDataSet" msdata:IsDataSet="true"
> msdata:MainDataTable="environ" msdata:UseCurrentLocale="true">
> <xs:complexType>
> <xs:choice minOccurs="0" maxOccurs="unbounded">
> <xs:element name="environ">
> <xs:complexType>
> <xs:sequence>
> <xs:element name="Environ" type="xs:string" minOccurs="0" />
> <xs:element name="Machine" type="xs:string" minOccurs="0" />
> <xs:element name="MyPath" type="xs:string" minOccurs="0" />
> <xs:element name="DBServer" type="xs:string" minOccurs="0" />
> </xs:sequence>
> </xs:complexType>
> </xs:element>
> </xs:choice>
> </xs:complexType>
> </xs:element>
> </xs:schema>
> <environ>
> <Environ>Development</Environ>
> <Machine>hogehage</Machine>
> <MyPath>DEV</MyPath>
> <DBServer>hogehage</DBServer>
> </environ>
> <environ>
> <Environ>Testing</Environ>
> <Machine>hogehage</Machine>
> <MyPath>TEST</MyPath>
> <DBServer>hogehage</DBServer>
> </environ>
> <environ>
> <Environ>Production</Environ>
> <Machine>hoge</Machine>
> <MyPath>APPL</MyPath>
> <DBServer>hoge</DBServer>
> </environ>
> <environ>
> <Environ>QA</Environ>
> <Machine>hogehage</Machine>
> <MyPath>APPL</MyPath>
> <DBServer>hogehage\QA</DBServer>
> </environ>
> </NewDataSet>
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -