vb.net Fieldsについて

解決


pink  2005-08-21 21:52:53  No: 91650  IP: [192.*.*.*]

はじめまして、pinkと申します。

OS:Windows2000
VB:.net

VBを使いはじめて一ヶ月なのですが、DBの値の取得で躓いています。
以下のソースで
        Dim cn As Object
        Dim rs As Object
        Dim sql As String

        sql = "SELECT aaa, bbb, ccc FROM XXX"

        '** ODBC 接続
        cn = CreateObject("ADODB.Connection")
        cn.Open("dsn=hoge;uid=sa;pwd=")
        cn.CursorLocation = 3

        '** レコードセットオープン
        rs = cn.Execute(sql)

        While Not rs.EOF
            ListBox1.Items.Add(rs.Fields("aaa").Value & "  " & rs.Fields("bbb").Value & _
            '"  " & rs.Fields("ccc").Value)
            rs.MoveNext()
        End While

        '** レコードセットクローズ
        rs.Close()
        '** ODBC 接続解除
        cn.Close()

Items.Addでエラーになります。
ちなみに、
rs("ccc").Valueもrs.Fields.Item("ccc").Value
もダメでした。
正しく値を取得するにはどうすればできるのでしょうか?

よろしくお願いします。

編集 削除
medaka  2005-08-22 08:39:44  No: 91651  IP: [192.*.*.*]

エラーの内容は?
Option Strict Onになってるなら文字型の連結できてないとか
rs("ccc").Value.ToString
Convert.ToString(rs("ccc").Value)
にしてみるとか

.netならDataReader使った方がいいと思うけど・・・

編集 削除
魔界の仮面弁士  2005-08-22 11:57:11  No: 91652  IP: [192.*.*.*]

そのコードは、Option Strict Off モードでのコードですね。

個人的には、VB.NET では『ADO.NET』を使って接続すべきだとは思いますが、
どうしても従来の『ADO』を使わねばならないのであれば、COMの解放処理を
忘れずに行うようにしてください。たとえば、このような感じになります。


sql = "SELECT aaa, bbb, ccc FROM XXX"
cn.CursorLocation = 3  'adUseClient
cn.Open(接続文字列)
rs = cn.Execute(sql)

'後から Fields/Field を明示的に解放できるよう、別の変数に取っておく
Dim Fs As Object = RS.Fields
Dim F1 As Object = Fs("aaa")
Dim F2 As Object = Fs("bbb")
Dim F3 As Object = Fs("ccc")

Do Until rs.EOF
    '一行で書いてしまうと、今回のエラーの原因を掴みにくいので、
    '値を取得する部分を、複数行の処理に分割しています。
    Dim Item As String
    Item = F1.Value.ToString() & "  "
    Item &= F2.Value.ToString() & "  "
    Item &= F3.Value.ToString()

    ListBox1.Items.Add(Item)

    rs.MoveNext()
Loop

'以下はCOMクラスの解放処理。解放する順番やCloseを呼び出す位置に注意すること。
If System.Runtime.InteropServices.Marshal.IsComObject(F3) Then
    System.Runtime.InteropServices.Marshal.ReleaseComObject(F3)
End If
If System.Runtime.InteropServices.Marshal.IsComObject(F2) Then
    System.Runtime.InteropServices.Marshal.ReleaseComObject(F2)
End If
If System.Runtime.InteropServices.Marshal.IsComObject(F2) Then
    System.Runtime.InteropServices.Marshal.ReleaseComObject(F2)
End If
If System.Runtime.InteropServices.Marshal.IsComObject(F1) Then
    System.Runtime.InteropServices.Marshal.ReleaseComObject(F1)
End If
If System.Runtime.InteropServices.Marshal.IsComObject(Fs) Then
    System.Runtime.InteropServices.Marshal.ReleaseComObject(Fs)
End If
rs.Close()
If System.Runtime.InteropServices.Marshal.IsComObject(rs) Then
    System.Runtime.InteropServices.Marshal.ReleaseComObject(rs)
End If
If System.Runtime.InteropServices.Marshal.IsComObject(cn) Then
    System.Runtime.InteropServices.Marshal.ReleaseComObject(cn)
End If
cn.Close()


なお、実際にはエラー発生時などに備えて、Try〜Catch〜Finally を使って
処理するべきなのですが、上記ではエラー対処を省略して書いています。


---- 以下、サポート技術情報より抜粋 ---
[高負荷下で ADO を .NET COM interop または Java で使用するとアクセス違反が発生する]
http://support.microsoft.com/kb/321415/ja

》 ActiveX Data Objects (ADO) を COM interop を介して使用するMicrosoft .NET プログラムや、
》 ADO を使用する Java プログラムで、ADO Connection オブジェクトの Close メソッドを
》 呼び出すと、アクセス違反が発生する場合があります。
(中略)
》 以下の 2 つのコーディング例を使用することで、この問題が発生する可能性を低く抑えることができます。 

》* COM オブジェクトの使用後、明示的に COM オブジェクトへの参照を解放する。 
》  →ReleaseComObject メソッドを使用してオブジェクトへの参照を解放することができる

》* ADO プライマリ相互運用アセンブリ (primary interop assembly) を使用する。

編集 削除
魔界の仮面弁士  2005-08-22 11:59:36  No: 91653  IP: [192.*.*.*]

> If System.Runtime.InteropServices.Marshal.IsComObject(cn) Then
>     System.Runtime.InteropServices.Marshal.ReleaseComObject(cn)
> End If
> cn.Close()

うっ。逆ですね。最後の部分は、

  cn.Close()
  If System.Runtime.InteropServices.Marshal.IsComObject(cn) Then
      System.Runtime.InteropServices.Marshal.ReleaseComObject(cn)
  End If

にしておいてください。m(_ _)m

編集 削除
pink  2005-09-01 22:47:28  No: 91654  IP: [192.*.*.*]

お返事が、大変々遅くなり申し訳ありません。
pinkです。

みなさんのご意見を参考にさせて頂き、
結局、ADO.NETを使いました。(使えました。)

ありがとうございました。

編集 削除
pink  2005-09-03 17:46:28  No: 91655  IP: [192.*.*.*]

解決のチェックを忘れていました!

編集 削除