トップ回答者
TableAdapterのクエリを変更する

質問
-
皆さん。こんにちは。いつも参考にさせて頂いています。
TableAdapterについてお聞きしたい事があります。
デザイナで作成するTableAdapterのクエリを、コードで変更することは可能でしょうか?Table1TableAdapter.Adapter.SelectCommand.CommandText="..."
の様にすると、SelectCommand がNothingの為、エラーとなってしまいます。
デザイナ上では、テーブルアダプタの、SelectCommand.CommandTextプロパティはあるので、
何故エラーになるか疑問です。その様にする理由は、任意のフィールを指定して検索する機能の為で、デザイナで作成するクエリは、
フィールド=パラメータ
の様に指定しなければならず、
フィールド=パラメータ や、
フィールド=パラメータ AND フィールド2=パラメータ
の様に、フィールド数を可変に出来ないため、WHERE 以降を追記するようにしたいのです。Visual Studio 2010 VB.netです。
何かお分かりの方、ご教授お願いします。
宜しくお願いします。
回答
-
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/- 編集済み trapemiyaModerator 2010年12月8日 5:53 追記
- 回答としてマーク しんなべ 2010年12月9日 2:12
-
やっぱり上の空で書いたコードは微妙におかしいですね(^^; ようやく時間が取れたのでちゃんと検証したコードを載せておきます。
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
すべての返信
-
たとえばこんな感じです
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
-
みなさん。こんにちは。
なかむらさん。いつも有難うございます。出来れば、既存のSelectCommandを使用したいと考えています。参考にさせて頂きます。
Chukiさん。調べたところ、TableAdapterのFillメソッドを一度実行すると、SelectCommandが生成されるようです。
if Me.UserNameTableAdapter.Adapter.SelectCommand is Nothing thenMe.UserNameTableAdapter.Fill(Me.ChukiTestDataSet.UserName)endif*ここでは、SelectCommandはNothingではなくなっている。
しかし、オブジェクト生成だけの為にFillを実行したくはないので、Fillを実行せずに、SelectCommandを生成出来たらと思案しています。
何かお分かりでしたら、ご教授お願いします。宜しくお願いします。
-
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/ -
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/- 編集済み trapemiyaModerator 2010年12月8日 5:53 追記
- 回答としてマーク しんなべ 2010年12月9日 2:12
-
#(追記)あっ、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
-
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/- 編集済み trapemiyaModerator 2010年12月8日 6:39 コード修正
-
やっぱり上の空で書いたコードは微妙におかしいですね(^^; ようやく時間が取れたのでちゃんと検証したコードを載せておきます。
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
-
目的がよく理解できていないのでハズレかもしれませんが・・・
> デザイナで作成するTableAdapterのクエリを、コードで変更することは可
> 能でしょうか?必要なクエリがウィザードベースで定義できない場合は別の手段があります。
Visual Studio のウィザードで生成した TableAdapter クラスは partial と
して定義されているので、自力でコードを書いて機能を拡張して目的を果たす
ことはできませんか?詳しくは以下のページが参考になると思います。
Microsoft Visual Studio 2005によるWebアプリケーション構築技法
7.6 データコンポーネント機能によるデータアクセスコンポーネントの開発
http://www.atmarkit.co.jp/fdotnet/bookpreview/vs2005webapp_07/vs2005webapp_07_04.htmlWeb アプリ開発関係の本ですが、基本的なことは windows アプリでも同じで
す。 -
みなさん。こんにちは。
Chukiさん。trapemiyaさん。SurferOnWwwさん。ご返事有難うございます。
trapemiyaさんご教授の方法を参考に以下の様にして解決しました。
・TableAdapterのパーシャルクラスに以下を定義
Public Sub SetSelectCommand()Me.Adapter.SelectCommand = Me.CommandCollection(0)End Sub
・使用する側で呼び出し
Dim ta As New userDataSetTableAdapters.UserTableAdapterta.SetSelectCommand()ta.Adapter.SelectCommand.CommandText += " WHERE field1=XXX and field2=YYY"ta.Fill(userDataSet.UserTable)
trapemiyaさん。丁寧に教えて頂いて、有難うございます。現実装として、WHERE以外のSELECT部分は固定で良いので、デザイナで定義し、WHERE以降のみ可変にする方法ですので、上記なコードとなりました。それ以上にご教授のコードは、とても参考になりますので、今後使用させて頂きます。
SurferOnWwwさん。ご教授のサイト、参考にさせて頂きます。
宜しくお願いします。