none
TableAdapterのクエリを変更する RRS feed

  • 質問

  • 皆さん。こんにちは。いつも参考にさせて頂いています。

    TableAdapterについてお聞きしたい事があります。
    デザイナで作成するTableAdapterのクエリを、コードで変更することは可能でしょうか?

    Table1TableAdapter.Adapter.SelectCommand.CommandText="..."

    の様にすると、SelectCommand がNothingの為、エラーとなってしまいます。
    デザイナ上では、テーブルアダプタの、SelectCommand.CommandTextプロパティはあるので、
    何故エラーになるか疑問です。

    その様にする理由は、任意のフィールを指定して検索する機能の為で、デザイナで作成するクエリは、
    フィールド=パラメータ
    の様に指定しなければならず、
    フィールド=パラメータ や、
    フィールド=パラメータ AND フィールド2=パラメータ
    の様に、フィールド数を可変に出来ないため、WHERE 以降を追記するようにしたいのです。

    Visual Studio 2010 VB.netです。

    何かお分かりの方、ご教授お願いします。
    宜しくお願いします。

    2010年12月8日 3:10

回答

  • Public Function FillEx(dataTable As TESTDataSet1.TESTDataTable) As Integer
     Me.Adapter.SelectCommand = Me.CommandCollection(0)
     Return Me.Fill(dataTable)
    End

    しかし、オブジェクト生成だけの為にFillを実行したくはないので、Fillを実行せずに、SelectCommandを生成
    出来たらと思案しています。
     

    TableAdapterのPartialクラスを作成して、そこで以下のようにされてみてはいかがでしょうか? 以下のコードは未検証です。(空で書いてます)

    Public Function FillEx(dataTable As TESTDataSet1.TESTDataTable) As Integer
     Me.Adapter.SelectCommand = Me.CommandCollection(0)
     Return Me.Fill(dataTable)
    End Function
    

    #(追記)あっ、SQL文の指定が無いですね。素直になかむらさんの方法でSqlCommandを作成して、Me.Adapter.
    SelectCommandにセットした方がよさそうな気がします。
     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2010年12月8日 5:48
    モデレータ
  • やっぱり上の空で書いたコードは微妙におかしいですね(^^; ようやく時間が取れたのでちゃんと検証したコードを載せておきます。

    Imports System.Data.SqlClient
    
    Public Class TableAdapterWhereChange
    
      Private Sub TableAdapterWhereChange_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'TODO: このコード行はデータを 'TESTDataSet.TEST' テーブルに読み込みます。必要に応じて移動、または削除をしてください。
        Me.TESTTableAdapter.Fill(Me.TESTDataSet.TEST)
      End Sub
    
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim parameters As SqlParameter() = {New SqlParameter("@param1", 5), New SqlParameter("@param2", 10)}
        Me.TESTTableAdapter.FillEx(Me.TESTDataSet.TEST, "select ID, TEST1, TEST2 from TEST where ID >= @param1 and ID <= @param2", parameters)
    
      End Sub
    End Class
    
    Namespace TESTDataSetTableAdapters
      Partial Public Class TESTTableAdapter
        Public Function FillEx(ByVal dataTable As TESTDataSet.TESTDataTable, ByVal sql As String, ByVal parameters As SqlParameter()) As Integer
          Dim command = New Global.System.Data.SqlClient.SqlCommand()
          command.Connection = Me.Connection
          command.CommandText = sql
          command.CommandType = Global.System.Data.CommandType.Text
          command.Parameters.AddRange(parameters)
    
          Me.Adapter.SelectCommand = command
    
          If (Me.ClearBeforeFill = True) Then
            dataTable.Clear()
          End If
          Dim returnValue As Integer = Me.Adapter.Fill(dataTable)
          Return returnValue
        End Function
    
      End Class
    End Namespace
    

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

すべての返信

  • 新しい SqlCommand を作成し、TableAdapter の SelectCommand プロパティに設定してはどうでしょうか。

     


    なかむら(http://d.hatena.ne.jp/griefworker)
    2010年12月8日 3:21
  • 単にタイミングの問題なのでは?

    どのイベントで代入されようとしていらっしゃいますか?

    Windowsフォームのクリックイベントなどでしたらご質問の代入形式で動作しました。

    2010年12月8日 3:43
  • たとえばこんな感じです

      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.UserNameTableAdapter.Adapter.SelectCommand.CommandText = "Select * From UserName Where ID = 1"
        Me.UserNameTableAdapter.Fill(Me.ChukiTestDataSet.UserName)
        Me.UserNameDataGridView.Update()
      End Sub
    
    2010年12月8日 3:48
  • みなさん。こんにちは。

    なかむらさん。いつも有難うございます。出来れば、既存のSelectCommandを使用したいと考えています。参考にさせて頂きます。

    Chukiさん。
    調べたところ、TableAdapterのFillメソッドを一度実行すると、SelectCommandが生成されるようです。

    if Me.UserNameTableAdapter.Adapter.SelectCommand is Nothing then
      Me.UserNameTableAdapter.Fill(Me.ChukiTestDataSet.UserName)
    endif
    *ここでは、SelectCommandはNothingではなくなっている。

    しかし、オブジェクト生成だけの為にFillを実行したくはないので、Fillを実行せずに、SelectCommandを生成
    出来たらと思案しています。

    何かお分かりでしたら、ご教授お願いします。
    宜しくお願いします。

    2010年12月8日 5:26
  • Table1TableAdapter.Adapter.SelectCommand.CommandText="..."

    の様にすると、SelectCommand がNothingの為、エラーとなってしまいます。
    デザイナ上では、テーブルアダプタの、SelectCommand.CommandTextプロパティはあるので、
    何故エラーになるか疑問です。

    SqlCommandはCommandCollectionで管理されており、TableAdapterによって「クエリの追加」を行う度にSqlCommandが新たに作成されてCommandCollectionに追加されていきます。最初のクエリはデフォルトでFillというメソッド名で作成され、2番目のクエリはデフォルトでFillbyというメソッド名で作成されます。それぞれのクエリにCommandCollectionにおけるそれぞれのSqlCommandが対応するわけです。
    実際にデータを読み込む際には、メソッド名に応じたSqlCommandが動的にAdapterのSelectCommandプロパティにセットされます。
    したがって、SelectCommand がNothingのためエラーになるのは、一度もFillなどのメソッドを実行していないからだと思われます。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2010年12月8日 5:29
    モデレータ
  • Public Function FillEx(dataTable As TESTDataSet1.TESTDataTable) As Integer
     Me.Adapter.SelectCommand = Me.CommandCollection(0)
     Return Me.Fill(dataTable)
    End

    しかし、オブジェクト生成だけの為にFillを実行したくはないので、Fillを実行せずに、SelectCommandを生成
    出来たらと思案しています。
     

    TableAdapterのPartialクラスを作成して、そこで以下のようにされてみてはいかがでしょうか? 以下のコードは未検証です。(空で書いてます)

    Public Function FillEx(dataTable As TESTDataSet1.TESTDataTable) As Integer
     Me.Adapter.SelectCommand = Me.CommandCollection(0)
     Return Me.Fill(dataTable)
    End Function
    

    #(追記)あっ、SQL文の指定が無いですね。素直になかむらさんの方法でSqlCommandを作成して、Me.Adapter.
    SelectCommandにセットした方がよさそうな気がします。
     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2010年12月8日 5:48
    モデレータ
  • #(追記)あっ、SQL文の指定が無いですね。素直になかむらさんの方法でSqlCommandを作成して、Me.Adapter.
    SelectCommandにセットした方がよさそうな気がします。

    Fillの前に追加しても、一発目のFillで上書きされますよー

     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      Me.UserNameTableAdapter.Adapter.SelectCommand = New SqlClient.SqlCommand("Select * From UserName Where Name = 1")
      Debug.Print(Me.UserNameTableAdapter.Adapter.SelectCommand.CommandText)
      Me.UserNameTableAdapter.Fill(Me.ChukiTestDataSet.UserName)
      Debug.Print(Me.UserNameTableAdapter.Adapter.SelectCommand.CommandText)
      Me.UserNameDataGridView.Update()
    
     End Sub
    
    【イミディエイトウィンドウ】
    
    Select * From UserName Where Name = 1
    SELECT Name, ID FROM dbo.UserName
    


     

    2010年12月8日 6:14
  • Fillの前に追加しても、一発目のFillで上書きされますよー

    そうでした。(^^; やはり、空で書くとダメか。まだまだ実力が足りませんね。そういいながら懲りずに空で書いてみる。(ごめんなさい)

    Public Function FillEx(ByVal dataTable As TESTDataSet.TESTDataTable, ByVal sql as String, ByVal parameters as SqlParameters) As Integer
      Dim command = New Global.System.Data.SqlClient.SqlCommand()
      command.Connection = Me.Connection
      command.CommandText = sql
      command.CommandType = Global.System.Data.CommandType.Text
      command.Parameters = parameters
    
      Me.Adapter.SelectCommand = command
      
      If (Me.ClearBeforeFill = true) Then
       dataTable.Clear
      End If
      Dim returnValue As Integer = Me.Adapter.Fill(dataTable)
      Return returnValue
    End Function

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2010年12月8日 6:26
    モデレータ
  • やっぱり上の空で書いたコードは微妙におかしいですね(^^; ようやく時間が取れたのでちゃんと検証したコードを載せておきます。

    Imports System.Data.SqlClient
    
    Public Class TableAdapterWhereChange
    
      Private Sub TableAdapterWhereChange_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'TODO: このコード行はデータを 'TESTDataSet.TEST' テーブルに読み込みます。必要に応じて移動、または削除をしてください。
        Me.TESTTableAdapter.Fill(Me.TESTDataSet.TEST)
      End Sub
    
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim parameters As SqlParameter() = {New SqlParameter("@param1", 5), New SqlParameter("@param2", 10)}
        Me.TESTTableAdapter.FillEx(Me.TESTDataSet.TEST, "select ID, TEST1, TEST2 from TEST where ID >= @param1 and ID <= @param2", parameters)
    
      End Sub
    End Class
    
    Namespace TESTDataSetTableAdapters
      Partial Public Class TESTTableAdapter
        Public Function FillEx(ByVal dataTable As TESTDataSet.TESTDataTable, ByVal sql As String, ByVal parameters As SqlParameter()) As Integer
          Dim command = New Global.System.Data.SqlClient.SqlCommand()
          command.Connection = Me.Connection
          command.CommandText = sql
          command.CommandType = Global.System.Data.CommandType.Text
          command.Parameters.AddRange(parameters)
    
          Me.Adapter.SelectCommand = command
    
          If (Me.ClearBeforeFill = True) Then
            dataTable.Clear()
          End If
          Dim returnValue As Integer = Me.Adapter.Fill(dataTable)
          Return returnValue
        End Function
    
      End Class
    End Namespace
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク しんなべ 2010年12月9日 2:12
    2010年12月8日 12:07
    モデレータ
  • 目的がよく理解できていないのでハズレかもしれませんが・・・

    > デザイナで作成するTableAdapterのクエリを、コードで変更することは可
    > 能でしょうか?

    必要なクエリがウィザードベースで定義できない場合は別の手段があります。

    Visual Studio のウィザードで生成した TableAdapter クラスは partial と
    して定義されているので、自力でコードを書いて機能を拡張して目的を果たす
    ことはできませんか?

    詳しくは以下のページが参考になると思います。

    Microsoft Visual Studio 2005によるWebアプリケーション構築技法
    7.6 データコンポーネント機能によるデータアクセスコンポーネントの開発
    http://www.atmarkit.co.jp/fdotnet/bookpreview/vs2005webapp_07/vs2005webapp_07_04.html

    Web アプリ開発関係の本ですが、基本的なことは windows アプリでも同じで
    す。

    2010年12月8日 15:23
  • みなさん。こんにちは。

    Chukiさん。trapemiyaさん。SurferOnWwwさん。ご返事有難うございます。

    trapemiyaさんご教授の方法を参考に以下の様にして解決しました。

    ・TableAdapterのパーシャルクラスに以下を定義

    Public Sub SetSelectCommand()
        Me.Adapter.SelectCommand = Me.CommandCollection(0)
    End Sub

    ・使用する側で呼び出し

    Dim ta As New userDataSetTableAdapters.UserTableAdapter
    ta.SetSelectCommand()
    ta.Adapter.SelectCommand.CommandText += " WHERE  field1=XXX and field2=YYY"
    ta.Fill(userDataSet.UserTable)


    trapemiyaさん。
    丁寧に教えて頂いて、有難うございます。
    現実装として、
    WHERE以外のSELECT部分は固定で良いので、デザイナで定義し、WHERE以降のみ可変にする
    方法ですので、上記なコードとなりました。
    それ以上にご教授のコードは、とても参考になりますので、今後使用させて頂きます。


    SurferOnWwwさん。
    ご教授のサイト、参考にさせて頂きます。

    宜しくお願いします。

    2010年12月9日 2:09