none
New SqlClient.SqlCommand() と Create.Command() RRS feed

  • 質問

  • いつもお世話になっております。
    とある参考書のサンプルプログラムで

            Using connection As New SqlClient.SqlConnection(My.Settings.project_jobConnectionString)

                Dim Command As SqlClient.SqlCommand = connection.CreateCommand()

                connection.Open()

                Dim dr As SqlClient.SqlDataReader

               cmbManager.Items.Add("(すべて)")

                Command.CommandText = "SELECT staff_code,staff_name FROM tbl_staff ORDER BY staff_code"

                dr = Command.ExecuteReader()

                Do While dr.Read
                    cmbManager.Items.Add(dr("staff_code") & ":" & dr("staff_name"))
                Loop

                dr.Close()

    (以下、略します)

    とありますが、これの Dim Command As SqlClient.SqlCommand = connection.CreateCommand() の部分を

     Dim Command As New SqlClient.SqlCommand() とすると、

     dr = Command.ExecuteReader() の部分で、「ExecuteReader: Connection プロパティは初期化されていません。」と
    怒られてしまいます。

    New SqlClient.SqlCommand() と Connection.CreateCommand() は
    記述の違いだけで、同じ意味だと思っていたのですが、どう違うのでしょうか?

    ご教示のほど、よろしくお願いいたします。

    2010年10月12日 15:14

回答

  • SqlCommandから発行されるSQLは、データーベースへの接続を通してデーターベースへ届きます。つまり、SqlCommandにはデーターベースへの接続を指定する必要があります。その指定は、SqlCommandのConnectionプロパティに接続を設定することによって行ないます。
    connection.CreateCommand()はSqlCommandのConnectionプロパティに接続(この場合はconnection)が設定された状態で、SqlCommandを作成します。
    一方、Dim Command As New SqlClient.SqlCommand()は、SqlCommandのインスタンスを生成するだけで、Connectionプロパティは何も設定されていません。したがって、以下のように接続を設定する必要があります。
    Command.Connection = connection
    このようにCommandに接続を設定してあげることにより、Commandは無事にSQLをデーターベースに届けることができるようになります。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク kei_chan_gt 2010年10月13日 14:48
    2010年10月12日 16:12
    モデレータ
  • 私なら

    Dim Command as New SqlClient.SqlCommand(cmdText) 

    ですね。SqlCommand の生成時は コネクションと切り離しておいて、あとからConnection プロパティに設定したり、DataAdapter に SqlCommand とコネクションを渡すケースが多いです。
    また SqlConnection に SqlCommand の生成責任を持たせるのは、私としては生理的に好きじゃありません。もっとも人によりケースにもよるので、どちらでも構わないとは思います。
    ついでに「どちらが普通か?」と聞かれても、この場合の 「普通」 の定義が難しいため、お答えしかねます。


    ひらぽん http://d.hatena.ne.jp/hilapon/
    • 回答としてマーク kei_chan_gt 2010年10月13日 14:48
    2010年10月13日 12:21
    モデレータ
  • どちらで記述するものなのでしょうか?

    どちらも機能的には全く差がありませんし、コーディング量も大差なく、パフォーマンス的にも大きな差があるとは思えませんから、どちらが優れているという明白な理由は見つからず、どちらを使っても良いというのが一般的な答えになると思います。では、どちらを使っても良いのになぜ両方のパターンがあるのでしょう?その答えを想像しながら書いてみます。
    通常、インスタンスの生成はNewを用いて行なうのが普通です。であれば、1.の方が自然な書き方ということになります。2.をよく見ると、ファクトリーパターンの形をしています。つまり、SqlConnectionというファクトリー(工場)にCreateCommand()メソッドで依頼し、SqlCommandインスタンスを手に入れています。結果的に1.も2.も最終的にSqlCommandを手に入れることに変わりないのですが、デザインパターンに差があるということになります。
    出来上がるアプリケーションは同じでも、どのようにデザインパターンを利用してロジックを組むかは様々です。1.と2.の違いも、それと同じようなことだと思うのです。つまり、普通にインスタンスを生成するか、ファクトリーパターンで生成するかの違いです。と言いましても、1.と2.の1行ずつの極めて狭い範囲では実質的な差はなく、気持ちの問題でしかないでしょう。

    少し誇大な文章になった気がします。いずれにしても実際にはどちらを使われても良いと思います。気軽に考えて良いと思いますよ。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク kei_chan_gt 2010年10月13日 14:48
    2010年10月13日 13:45
    モデレータ
  • 1.も2.も接続先が明示的にSQL Serverに限られます。(SqlCommandクラスなので。)
    ただし2.に近い別の記述方法で

    Dim Command As System.Data.Common.DbCommand = connection.CreateDbCommand()

    とするとデータベースエンジンに依らない記述ができます。もちろんconnectionインスタンスを作成するときも別の作成の仕方になりますが。

    • 回答としてマーク kei_chan_gt 2010年10月13日 15:31
    2010年10月13日 15:13

すべての返信

  • SqlCommandから発行されるSQLは、データーベースへの接続を通してデーターベースへ届きます。つまり、SqlCommandにはデーターベースへの接続を指定する必要があります。その指定は、SqlCommandのConnectionプロパティに接続を設定することによって行ないます。
    connection.CreateCommand()はSqlCommandのConnectionプロパティに接続(この場合はconnection)が設定された状態で、SqlCommandを作成します。
    一方、Dim Command As New SqlClient.SqlCommand()は、SqlCommandのインスタンスを生成するだけで、Connectionプロパティは何も設定されていません。したがって、以下のように接続を設定する必要があります。
    Command.Connection = connection
    このようにCommandに接続を設定してあげることにより、Commandは無事にSQLをデーターベースに届けることができるようになります。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク kei_chan_gt 2010年10月13日 14:48
    2010年10月12日 16:12
    モデレータ
  • trapemiya さま

    いつもありがとうございます。
    なるほど、ありがとうございます<(_)>

    ちなみに普通、
    1.Dim Command as New SqlClient.SqlCommand(cmdText,SqlClient.SqlConnection) または、
    2.Dim Command As SqlClient.SqlCommand = connection.CreateCommand()
      Command.CommandText = "Select ○ From △"

    どちらで記述するものなのでしょうか?
    ご教示お願いいたします<(_)>

    2010年10月13日 11:57
  • 私なら

    Dim Command as New SqlClient.SqlCommand(cmdText) 

    ですね。SqlCommand の生成時は コネクションと切り離しておいて、あとからConnection プロパティに設定したり、DataAdapter に SqlCommand とコネクションを渡すケースが多いです。
    また SqlConnection に SqlCommand の生成責任を持たせるのは、私としては生理的に好きじゃありません。もっとも人によりケースにもよるので、どちらでも構わないとは思います。
    ついでに「どちらが普通か?」と聞かれても、この場合の 「普通」 の定義が難しいため、お答えしかねます。


    ひらぽん http://d.hatena.ne.jp/hilapon/
    • 回答としてマーク kei_chan_gt 2010年10月13日 14:48
    2010年10月13日 12:21
    モデレータ
  • どちらで記述するものなのでしょうか?

    どちらも機能的には全く差がありませんし、コーディング量も大差なく、パフォーマンス的にも大きな差があるとは思えませんから、どちらが優れているという明白な理由は見つからず、どちらを使っても良いというのが一般的な答えになると思います。では、どちらを使っても良いのになぜ両方のパターンがあるのでしょう?その答えを想像しながら書いてみます。
    通常、インスタンスの生成はNewを用いて行なうのが普通です。であれば、1.の方が自然な書き方ということになります。2.をよく見ると、ファクトリーパターンの形をしています。つまり、SqlConnectionというファクトリー(工場)にCreateCommand()メソッドで依頼し、SqlCommandインスタンスを手に入れています。結果的に1.も2.も最終的にSqlCommandを手に入れることに変わりないのですが、デザインパターンに差があるということになります。
    出来上がるアプリケーションは同じでも、どのようにデザインパターンを利用してロジックを組むかは様々です。1.と2.の違いも、それと同じようなことだと思うのです。つまり、普通にインスタンスを生成するか、ファクトリーパターンで生成するかの違いです。と言いましても、1.と2.の1行ずつの極めて狭い範囲では実質的な差はなく、気持ちの問題でしかないでしょう。

    少し誇大な文章になった気がします。いずれにしても実際にはどちらを使われても良いと思います。気軽に考えて良いと思いますよ。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク kei_chan_gt 2010年10月13日 14:48
    2010年10月13日 13:45
    モデレータ
  • ひらぽん さま
    trapemiya さま

    ありがとうございます<(_)>
    安心しました。

    Visual Basic は同じような用途でも多種多様なコーディングの仕方があり(C#など他の言語でもそうなのでしょうか?)
    そのせいでとっても混乱しています(><)

    VB6.0→VB.NETになり、更にそれに拍車がかかったような(-_-)
    特に、6.0をかじっている途中で、VBのバージョンが上がってしまい、
    仕方なくそれに引きづられるようにズルズルと上位言語を勉強せざるを得なかった、
    私のような一般ユーザーには混乱の極みです。

    Msgbox と Messagebox.show ってどう違うの?
    .NETでは後者を使うの?でも前者も使える。なんで?

    2005になって、TableAdapter が登場したけど、
    なんで参考書はいまだに DataAdapter を使っているの?

    従来の接続型と、.NETの非接続型の使い分けの基準がわからない。
    非接続型の使い方がヘタだと、メモリを多量に食って、最悪フリーズだって?(ヒーッ(><))

    などなど。

    ですのでまた「初歩的な、おバカ」な質問をするかも知れませんが
    どうかご教示のほどよろしくお願いいたします<(_)>

    夢は、職場で使う「発注入庫管理ソフト」を自分で作成することなのですが、
    この分だといつになることやら。

    (少々あきらめ入ってます。グチ言ってすみません)

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

    2010年10月13日 14:48
  • 1.も2.も接続先が明示的にSQL Serverに限られます。(SqlCommandクラスなので。)
    ただし2.に近い別の記述方法で

    Dim Command As System.Data.Common.DbCommand = connection.CreateDbCommand()

    とするとデータベースエンジンに依らない記述ができます。もちろんconnectionインスタンスを作成するときも別の作成の仕方になりますが。

    • 回答としてマーク kei_chan_gt 2010年10月13日 15:31
    2010年10月13日 15:13
  • 佐祐理 さま

    ご回答ありがとうございます。
    できれば一番パフォーマンスのよいコーディングをしたい
    と思い色んな参考書を購入しては読みふけっていますが、
    読めば読むほど悩んでしまいます。

    これからもどうかご教示のほど、よろしくお願いいたします<(_)>

    2010年10月13日 15:31