投稿者 るきお  (社会人) 投稿日時 2009/2/28 07:30:55
>今コネクションを
>Dim Cn As SqlClient.SqlConnection
>で宣言しているのですが、もう1つ別名で同じ宣言をすればいいということなのですか?
宣言も必要ですが、それだけでいいわけではありませんしここは問題の本質ではありません。

>別クラスが読まれたときに「Cn」をNewしているのですが、それでもだめなのでしょうか?
Newして使いまわしているのならOKです。
けれど同じ変数で複数の接続を表現するようなコードを書くと、わかりにくくなって大変だと思います。

以下の例では同様のエラーが発生します。
        '▼接続を確立 
        Dim cn1 As New SqlConnection
        cn1.ConnectionString = "Server=.;Integrated Security = True"
        cn1.Open()

        '▼クエリ生成 
        Dim sqlCm1 As New SqlCommand("SELECT * FROM sys.databases", cn1)

        '▼DataReader生成 
        Dim reader As SqlDataReader
        reader = sqlCm1.ExecuteReader

        '▼ループを回しつつ、同じ接続でExecuteNonQuery 
        While reader.Read
            Dim sqlCm2 As New SqlCommand("SELECT * FROM sys.objects", cn1)

            'ここでエラー 
            sqlCm2.ExecuteNonQuery()
        End While

        '▼後処理 
        reader.Close()
        cn1.Close()

        MsgBox("OK")


これを接続を2つ使ってエラーがでないように書き換えると次のようになります。
        '▼接続を確立 
        Dim cn1 As New SqlConnection
        cn1.ConnectionString = "Server=.;Integrated Security = True"
        cn1.Open()

        '▼クエリ生成 
        Dim sqlCm1 As New SqlCommand("SELECT * FROM sys.databases", cn1)

        '▼DataReader生成 
        Dim reader As SqlDataReader
        reader = sqlCm1.ExecuteReader

        '▼2つ目の接続を確立 
        Dim cn2 As New SqlConnection("Server=.;Integrated Security = True")
        cn2.Open()

        '▼1つ目の接続でループを回しつつ、2つ目の接続でExecuteNonQuery 
        While reader.Read
            Dim sqlCm2 As New SqlCommand("SELECT * FROM sys.objects", cn2)
            sqlCm2.ExecuteNonQuery()
        End While

        '▼後処理 
        cn2.Close()
        reader.Close()
        cn1.Close()

        MsgBox("OK")


ただし、同時にデータベースに接続するのはできるだけさけるべきであり、このような修正はあまりお勧めしません。
DataTableを使えば同時にデータベースに接続する必要はなくなります。

DataTableを使って書き換えると次のようになります。
        '▼接続を確立 
        Dim cn1 As New SqlConnection
        cn1.ConnectionString = "Server=.;Integrated Security = True"
        cn1.Open()

        '▼クエリ生成 
        Dim sqlCm1 As New SqlCommand("SELECT * FROM sys.databases", cn1)

        '▼DataTableにデータを格納する 
        Dim adapter As New SqlDataAdapter(sqlCm1)
        Dim table As New DataTable
        adapter.Fill(table)

        '▼DataTableでループを回しつつ、1つ目の接続でExecuteNonQuery 
        For Each row As DataRow In table.Rows
            Dim sqlCm2 As New SqlCommand("SELECT * FROM sys.objects", cn1)
            sqlCm2.ExecuteNonQuery()
        Next

        '▼後処理 
        cn1.Close()

        MsgBox("OK")


ただし、いつでもDataTableを使えばよいというわけではなく、DataReaderなどとの適切な使い分けは必要です。
たとえばDataTableはデータをクライアント側にごっそりもってくるためデータの量が多い場合はリソースを消費しパフォーマンスが悪化します。
DataReaderはサーバー側との接続を開いた状態にしておく必要があるので、今回の事例のように接続を占有してしまいます。また前方にしか移動できず値の更新もできません。

ちなみに私はほとんどの場面でDataReaderではなくDataTableを使用しています。