トップ回答者
GridViewにすべてのデータを表示させ、条件によって表示を変更させたいのですが

質問
-
GridViewに複数のテーブルをリレーションでまとめて作ったDataSet1.xsdを使い
データベースの情報をすべて表示させ、
TextBox1、TextBox2に条件が入った場合はその条件にあったものに
絞り込めるGridViewを表示できるようにしたいのですがQUERYの書き方がよくわかりません。
現時点ではDataSet1.xsdに項目(名前)と(クラス)のフィルタに【?】を入れて作ったQUERYを使ってみましたが
実行するとTextBox1、TextBox2の情報が両方とも一致している場合のみしかGridViewが表示されません。どのようにしたら最初はすべてのデータを表示し、条件を入れた場合のみその条件にあうものが表示されるようになるのでしょうか?
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>無題のページ</title>
</head>
<body>
<form id="form1" runat="server">
<div>
名前<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
クラス<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="検索" />
<br />
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" DataSourceID="ObjectDataSource1">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True"
SortExpression="ID" />
<asp:BoundField DataField="名前" HeaderText="名前" SortExpression="名前" />
<asp:BoundField DataField="性別" HeaderText="性別" SortExpression="性別" />
<asp:BoundField DataField="クラス" HeaderText="クラス" SortExpression="クラス" />
<asp:BoundField DataField="国語" HeaderText="国語" SortExpression="国語" />
<asp:BoundField DataField="算数" HeaderText="算数" SortExpression="算数" />
<asp:BoundField DataField="社会" HeaderText="社会" SortExpression="社会" />
<asp:BoundField DataField="理科" HeaderText="理科" SortExpression="理科" />
</Columns>
</asp:GridView>
<aspbjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetDataBy"
TypeName="DataSet1TableAdapters.DataTable1TableAdapter">
<SelectParameters>
<asp:ControlParameter ControlID="TextBox1" Name="Param1"
PropertyName="Text" Type="String" />
<asp:ControlParameter ControlID="TextBox2" Name="Param2"
PropertyName="Text" Type="String" />
</SelectParameters>
</aspbjectDataSource>
</div>
</form>
</body>
</html>
回答
-
komi1 さんからの引用 GridViewに複数のテーブルをリレーションでまとめて作ったDataSet1.xsdを使い
データベースの情報をすべて表示させ、
TextBox1、TextBox2に条件が入った場合はその条件にあったものに
絞り込めるGridViewを表示できるようにしたいのですがQUERYの書き方がよくわかりません。
現時点ではDataSet1.xsdに項目(名前)と(クラス)のフィルタに【?】を入れて作ったQUERYを使ってみましたが
実行するとTextBox1、TextBox2の情報が両方とも一致している場合のみしかGridViewが表示されません。どのようにしたら最初はすべてのデータを表示し、条件を入れた場合のみその条件にあうものが表示されるようになるのでしょうか?
前回の例に倣って public partial class DataTable1TableAdapter を作って、例え
ば GetDataBy(string name, string cls) というようなメソッドを作って、name と
cls の値によって SELECT クエリを切り替えるようなコードを実装すれば実現でき
ます。例えば、以下のような感じ。(コードは検証してませんので注意)
Code Snippetstring query;
SqlDataAdapter adapter;if (name == String.Empty && cls == String.Empty)
{
query = "SELECT * FROM table";
adapter = new SqlDataAdapter(query, this.Connection);
}
else if (name == String.Empty && cls != String.Empty)
{
query = "SELECT * FROM table WHERE cls=@cls";
adapter = new SqlDataAdapter(query, this.Connection);
adapter.SelectCommand.Parameters.AddWithValue("@cls", cls);
}
else if (name != String.Empty && cls == String.Empty)
{
query = "SELECT * FROM table WHERE name=@name";
adapter = new SqlDataAdapter(query, this.Connection);
adapter.SelectCommand.Parameters.AddWithValue("@name", name);
}
else
{
query = "SELECT * FROM table WHERE name=@name AND cls=@cls";
adapter = new SqlDataAdapter(query, this.Connection);
adapter.SelectCommand.Parameters.AddWithValue("@name", name);
adapter.SelectCommand.Parameters.AddWithValue("@cls", cls);
}XxxxxxDataSet dataset = new XxxxxxDataSet();
adapter.Fill(dataset.Xxxxxx);
return dataset.Xxxxxx;
すべての返信
-
komi1 さんからの引用 GridViewに複数のテーブルをリレーションでまとめて作ったDataSet1.xsdを使い
データベースの情報をすべて表示させ、
TextBox1、TextBox2に条件が入った場合はその条件にあったものに
絞り込めるGridViewを表示できるようにしたいのですがQUERYの書き方がよくわかりません。
現時点ではDataSet1.xsdに項目(名前)と(クラス)のフィルタに【?】を入れて作ったQUERYを使ってみましたが
実行するとTextBox1、TextBox2の情報が両方とも一致している場合のみしかGridViewが表示されません。どのようにしたら最初はすべてのデータを表示し、条件を入れた場合のみその条件にあうものが表示されるようになるのでしょうか?
前回の例に倣って public partial class DataTable1TableAdapter を作って、例え
ば GetDataBy(string name, string cls) というようなメソッドを作って、name と
cls の値によって SELECT クエリを切り替えるようなコードを実装すれば実現でき
ます。例えば、以下のような感じ。(コードは検証してませんので注意)
Code Snippetstring query;
SqlDataAdapter adapter;if (name == String.Empty && cls == String.Empty)
{
query = "SELECT * FROM table";
adapter = new SqlDataAdapter(query, this.Connection);
}
else if (name == String.Empty && cls != String.Empty)
{
query = "SELECT * FROM table WHERE cls=@cls";
adapter = new SqlDataAdapter(query, this.Connection);
adapter.SelectCommand.Parameters.AddWithValue("@cls", cls);
}
else if (name != String.Empty && cls == String.Empty)
{
query = "SELECT * FROM table WHERE name=@name";
adapter = new SqlDataAdapter(query, this.Connection);
adapter.SelectCommand.Parameters.AddWithValue("@name", name);
}
else
{
query = "SELECT * FROM table WHERE name=@name AND cls=@cls";
adapter = new SqlDataAdapter(query, this.Connection);
adapter.SelectCommand.Parameters.AddWithValue("@name", name);
adapter.SelectCommand.Parameters.AddWithValue("@cls", cls);
}XxxxxxDataSet dataset = new XxxxxxDataSet();
adapter.Fill(dataset.Xxxxxx);
return dataset.Xxxxxx; -
komi1 さんからの引用 GridViewに複数のテーブルをリレーションでまとめて作ったDataSet1.xsdを使い
データベースの情報をすべて表示させ、
TextBox1、TextBox2に条件が入った場合はその条件にあったものに
絞り込めるGridViewを表示できるようにしたいのですがQUERYの書き方がよくわかりません。
現時点ではDataSet1.xsdに項目(名前)と(クラス)のフィルタに【?】を入れて作ったQUERYを使ってみましたが
実行するとTextBox1、TextBox2の情報が両方とも一致している場合のみしかGridViewが表示されません。どのようにしたら最初はすべてのデータを表示し、条件を入れた場合のみその条件にあうものが表示されるようになるのでしょうか?
条件を下記の様に編集するとか。
# または、LIKE検索WHERE (@Param1 IS NULL
OR 名前 = @Param1)
AND (@Param2 IS NULL
OR クラス = @Param2)
-
既に回答が出ていますが、ストアドプロシージャを使用して、そこでSQL文を組み立てるということも可能です。(単純に組み立てるとSQLインジェクションの原因になります!)
この方法はもっと検索条件が複雑になった場合でも応用が効きますので、私が一番多く使うパターンです。TableAdapterはデータセットなどを簡単に扱えるようにラップしたものですから、それだけ応用が効きにくくなっています。そこで、応用を行うのをストアドプロシージャ側に持っていっているのです。
また、ObjectDataSourceを使用されていますので、もし、TableAdapterに拘らないのであれば、そこでSQL文を組み立てることも可能です。(単純に組み立てるとSQLインジェクションの原因になります!)
SqlDataSourceを使うのであれば、やはりSQL文を組み立てることが可能です。(単純に組み立てるとSQLインジェクションの原因になります!)
-
Z9M9Z さんからの引用 私がやっているのは
SELECT * FROM table WHERE (@name IS NULL OR name=@name) AND (@cls IS NULL OR cls=@cls)
として条件が設定されない場合は@name, @clsにNULLが来るようにしています。
.NET の世界では String.Empty, null, DBNull.Value は違うものとして
区別されます。SQL Server の世界でも、MSDN ライブラリよれば「NULL 値は 0、空白、
長さ 0 の文字列 ("" など) のいずれとも異なります。」とのことです。SELECT ... WHERE @xxxxx IS NULL のパラメータ値を以下のように
(xsd ファイルから自動生成されるコードがそのようになっています)、テキ
ストボックスの初期値である String.Empty に設定した場合、
Code SnippetsqlCommand.CommandText = "SELECT * FROM table WHERE (@xxxxx IS NULL)";
sqlCommand.Parameters.Add(new SqlParameter("@xxxxx"));
sqlCommand.Parameters[0].Value = String.Empty;WHERE 句の条件は '' IS NULL となり、FALSE と評価され、何も抽出され
ないという結果になるはずです。・・・と書いてレスを終わりにしようと思っていましたが、二人の方が違う意見
を言われるので、念のため実際にコードを書いて検証してみました。
結果はやはり '' IS NULL は FALSE と評価されたようで、何も抽出されな
かったです。自分が知らないだけで、何かやり方があるのでょうか?
-
>結果はやはり '' IS NULL は FALSE と評価されたようで、何も抽出されな
>かったです。うまく言えませんが、VWDのデザイナでTextBoxをSQLDataSourceのパラメータに設定すると、
Code Snippet<SelectParameters>
<asp:ControlParameter ControlID="TextBox1" Name="姓" PropertyName="Text" DefaultValue="" ConvertEmptyStringToNull="False" />のようにConvertEmptyStringToNullというパラメータが設定できます。これはDefaultではTrueであり、
TextBox1が空文字列の場合にNullに変換してくれます。
-
いつもお世話になります。
試したのですが、すみません。使い方がわかりません。
下記コードで
①名前
②クラス
③Me.Connection
④Dim dataset As New XxxxxxDataSet
⑤adapter.Fill(dataset.Xxxxxx)
⑥Return dataset.Xxxxxxが波線となるのですが
名前=TextBox1.text
クラス=TextBox2.textですよね?どうしたら、エラーがでなくなるのでしょうか?
③はConnectionはDataSet1TableAdapters.DataTable1TableAdapterのメンバではありません。というエラー内容です。
④~⑥はXXXXに何をいれたらいいのか、値を返すものをつくるコードなんでしょうが、
よく理解できません。
ご教授いただけないでしょうか?よろしくお願いいたします。
Imports System
Imports System.Data
Imports System.Data.SqlClientNamespace DataSet1TableAdapters
Partial Public Class DataTable1TableAdapter
Dim query As String
Dim adapter As SqlDataAdapterPublic Sub KENSAKU()
'名前がカラ、クラスがカラの時はqueryに全部で
If TextBox1.text = [String].Empty AndAlso クラス = [String].Empty Then
query = "SELECT * FROM table"
adapter = New SqlDataAdapter(query, Me.Connection)
'名前がカラでクラスがカラでない場合はqueryにクラスで絞るで
ElseIf 名前 = [String].Empty AndAlso クラス <> [String].Empty Then
query = "SELECT * FROM table WHERE クラス=@クラス"
adapter = New SqlDataAdapter(query, Me.Connection)
adapter.SelectCommand.Parameters.AddWithValue("@クラス", クラス)
'名前がカラでなくクラスがカラの場合はqueryに名前で絞るで
ElseIf 名前 <> [String].Empty AndAlso クラス = [String].Empty Then
query = "SELECT * FROM table WHERE 名前=@名前"
adapter = New SqlDataAdapter(query, Me.Connection)
adapter.SelectCommand.Parameters.AddWithValue("@名前", 名前)
'名前もクラスもカラでない場合はqueryに名前、クラスで絞るで
Else
query = "SELECT * FROM table WHERE 名前=@名前 AND クラス=@クラス"
adapter = New SqlDataAdapter(query, Me.Connection)
adapter.SelectCommand.Parameters.AddWithValue("@名前", 名前)
adapter.SelectCommand.Parameters.AddWithValue("@クラス", クラス)
End IfDim dataset As New XxxxxxDataSet
adapter.Fill(dataset.Xxxxxx)
Return dataset.Xxxxxx
End Sub
End Class
End Namespace -
> TextBox1が空文字列の場合にNullに変換してくれます。
null は DBNull.Value とは違うので、先の例で、
Code SnippetsqlCommand.Parameters[0].Value = null;
のようにするとエラーになるはずです。もちろん、データも
抽出されません。ちなみに、
Code SnippetsqlCommand.Parameters[0].Value = DBNull.Value;なら OK です。DB のテーブルのフィールドが NULL 許容であ
る必要がありますが。でも、確かに SqlDataSource 経由でデータバインドされたテ
キストボックスが空白のまま Insert, Update すると DB の
該当フィールドは NULL になるので、null が DBNull.Value
に変換されるのかもしれないですね。ObjectDataSource の場合も同じかもしれませんが、やっぱり、
それに頼らず自力でコードを書くのが、個人的には良いと思い
ます。 -
komi1 さんからの引用 下記コードで
①名前
②クラス
③Me.Connection
④Dim dataset As New XxxxxxDataSet
⑤adapter.Fill(dataset.Xxxxxx)
⑥Return dataset.Xxxxxxが波線となるのですが
名前=TextBox1.text
クラス=TextBox2.textですよね?どうしたら、エラーがでなくなるのでしょうか?
③はConnectionはDataSet1TableAdapters.DataTable1TableAdapterのメンバではありません。というエラー内容です。
④~⑥はXXXXに何をいれたらいいのか、値を返すものをつくるコードなんでしょうが、
よく理解できません。
失礼な言い方かもしれませんが、あれからあまり勉強の方は進んでないよう
で、依然として話が通じない状況のようです。
掲示板のやり取りで、先にアップしたコードを完成をさせるのは無理っぽいの
で、別の手を考えます(今日は遅いのでまた明日)。
それとは別に、他の方から提案のあった、@xxxxx IS NULL を追加するのを
試してみてください。
-
SurferOnWww さんからの引用 > TextBox1が空文字列の場合にNullに変換してくれます。
null は DBNull.Value とは違うので、先の例で、
Code SnippetsqlCommand.Parameters[0].Value = null;
のようにするとエラーになるはずです。もちろん、データも
抽出されません。# 私もZ9M9Zさんと同様のコメントをしたので追加でコメントしておきます
MSDN
SurferOnWww さんからの引用 | |
|
最初の私の案はちょっと難しそうで、@xxxx IS NULL 案も元々 NULL 不可だと
すると NULL 許容に変えて思わぬところで問題が出る可能性を排除できないと
いうことで、@xxxx IS NULL 案を参考にそれを少し変更して以下のようにする
のが簡単でよさそうです。
(1) TextBox.Text の初期値は "ALL" にしておく。(注)
(2) SELECT クエリの WHERE 句は以下のようにする。
WHERE (@name = 'ALL' OR 名前 = @name) AND (@cls = 'ALL' OR クラス = @cls)
そんなクエリでいいのかという気もしますが、一応それで動くことは検証済み
です。
(注)TextBox に替えて DropDownList を2つ使い、それぞれに名前とクラス
をデータバインドして、それから選ぶようにするのが、SQL インジェク
ション防止やユーザビリティ向上によさそうです。
karashima さんからの引用 | |
|
DB のフィールドが NULL 不可に設定されている場合、自動生成される GetDataByXxxx メ
ソッドのコードでは null を受け付けないのですが、それをすると、例えば引数が int だったの
が int? になって、さらに null を受けたときは DBNull.Value に変えるコードに変更されますね。
ご回答いただきありがとうございます。
SQLserverを使ってやってみましたら、うまく思うとおりの動作ができました。
WHERE (@Param1 = 'ALL') AND (@Param2 = 'ALL') OR
(@Param1 = 'ALL') AND (情報.クラス = @Param2) OR
(@Param2 = 'ALL') AND (情報.名前 = @Param1) OR
(情報.クラス = @Param2) AND (情報.名前 = @Param1)
ですが、Accessを使うとどのようにしたらいいのでしょうか?
WHERE (? = 'ALL') AND (? = 'ALL') OR
(? = 'ALL') AND (情報.クラス = ?) OR
(? = 'ALL') AND (情報.名前 = ?) OR
(情報.クラス = ?) AND (情報.名前 = ?)
SQLでは「?」を入れると項目ごとに@Param1 、@Param2となるのですが
Accessではどの項目でも?と表示されてしまい、
思うような操作ができません。
Z9M9Z さんからの引用 | |
|
ALL を使うことを提案した理由は、自分が書いたコードでコントロール可能だ
からです。
「コントロール可能」というのは、ALL とすれば、そのまま ALL が渡されるの
で、結果が自分の思ったとおりになるという意味です。
TextBox から SQL Server に投げられるクエリ文字の間には、ControlParameter,
ObjectDataSource, TableAdapter, ADO.NET ライブラリがあります。空白の場合、
それがそこでどのように変換されていくか見えないところがあって、自分的にはあ
まり気分が良くないんです。
@xxxx IS NULL とか @xxxx = '' の場合、TextBox の空白がどのように変換され
て、最終的に期待する文字(この場合 NULL とか '')に変換されるか、ライブラ
リ任せというのが気に入らないです。まあ、それは自分がプロパティの設定など
に無知だからで、熟知している方には当てはまらないかもしれませんが。
もう一つの理由は、空白より ALL(日本語で「全部」などとしてもいいです)と表示さ
れていた方がユーザビリティの面でよさそうだと思ったこともあります。
WHERE (? = 'ALL') AND (? = 'ALL') OR
(? = 'ALL') AND (クラス = ?) OR
(? = 'ALL') AND (名前 = ?) OR
(クラス = ?) AND (名前 = ?)
TextBox1、TextBox2、TextBox1、TextBox2、TextBox2、TextBox1、TextBox2、TextBox1で
思うような動作ができるようになりました。
SQLとACCESSでは違うんですね。
今回教えていただいたのを元にいろいろな条件指定をしていきたいと思います。
教えていただき本当にありがとうございました。
前のレスに書いた、TextBox に替えて DropDownList を使う案も検討してみてく
ださい。実際に試してみると、たぶん、そのほうが良いと思うでしょう。
TextBox1, TextBox2 を以下のように置き換えれば実現できると思います。デー
タベースのフォルダ名/名前(下記では App_Data/Access.mdb)、フィールド名
(下記では「名前」「クラス」 )、テーブル名(下記では table)は実際にあわせて
書き直してください。
<asp:AccessDataSource ID="AccessDataSource1"
runat="server"
DataFile="~/App_Data/Access.mdb"
SelectCommand="SELECT DISTINCT [名前] FROM [table]">
</asp:AccessDataSource>
<asp:DropDownList ID="DropDownList1"
runat="server"
DataSourceID="AccessDataSource1"
AppendDataBoundItems="True"
DataTextField="名前"
DataValueField="名前">
<asp:ListItem Value="ALL">ALL</asp:ListItem>
</asp:DropDownList>
<asp:AccessDataSource ID="AccessDataSource2"
runat="server"
DataFile="~/App_Data/Access.mdb"
SelectCommand="SELECT DISTINCT [クラス] FROM [table]">
</asp:AccessDataSource>
<asp:DropDownList ID="DropDownList2"
runat="server"
DataSourceID="AccessDataSource2"
AppendDataBoundItems="True"
DataTextField="クラス"
DataValueField="クラス">
<asp:ListItem Value="ALL">ALL</asp:ListItem>
</asp:DropDownList>
ドロップダウンリストにして出来ました。
ありがとうございます。これで、文字間違えなどの問題が防げます。
ですが、Accessのほうはうまくできたのですが
SQL版の方がうまくできません。
クエリビルダ上では
WHERE (@Param1 = 'ALL') AND (@Param2 = 'ALL') OR
(@Param1 = 'ALL') AND (情報.クラス = @Param2) OR
(@Param2 = 'ALL') AND (情報.名前 = @Param1) OR
(情報.クラス = @Param2) AND (情報.名前 = @Param1)
でクエリの実行で
@Param1=ALL・@Param2=ALL 全て表示
@Param1=相沢・@Param2=ALL 相沢さんの情報のみ表示
@Param1=ALL・@Param2=A クラスAのみ表示
@Param1=相沢・@Param2=A 相沢さんの情報のみ表示
と、うまく思ったとおりの表示がされるのですが
これを実際にaspxでGridViewに表示させると
@Param1=ALL・@Param2=ALL 何も表示されない
@Param1=相沢・@Param2=ALL 何も表示されない
@Param1=ALL・@Param2=A クラスAのみ表示
@Param1=相沢・@Param2=A 相沢さんの情報のみ表示
というような@Param1がうまくできていない表示となってしまいます。
クリエビルダ上ではうまく動くのになぜできなくなってしますのでしょうか?
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>無題のページ</title>
</head>
<body>
<form id="form1" runat="server">
<p>
名前<aspropDownList ID="DropDownList1" runat="server"
AppendDataBoundItems="True" DataSourceID="ObjectDataSource1" DataTextField="名前"
DataValueField="名前">
<asp:ListItem>ALL</asp:ListItem>
</aspropDownList>
<aspbjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetData"
TypeName="DataSet1TableAdapters.DataTable1TableAdapter">
</aspbjectDataSource>
クラス<aspropDownList ID="DropDownList2" runat="server"
AppendDataBoundItems="True" DataSourceID="ObjectDataSource2"
DataTextField="クラス" DataValueField="クラス">
<asp:ListItem>ALL</asp:ListItem>
</aspropDownList>
<asp:Button ID="Button1" runat="server" Text="Button" />
<aspbjectDataSource ID="ObjectDataSource2" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetData"
TypeName="DataSet1TableAdapters.DataTable1TableAdapter">
</aspbjectDataSource>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" DataSourceID="ObjectDataSource3">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True"
SortExpression="ID" />
<asp:BoundField DataField="名前" HeaderText="名前" SortExpression="名前" />
<asp:BoundField DataField="性別" HeaderText="性別" SortExpression="性別" />
<asp:BoundField DataField="クラス" HeaderText="クラス" SortExpression="クラス" />
<asp:BoundField DataField="国語" HeaderText="国語" SortExpression="国語" />
<asp:BoundField DataField="算数" HeaderText="算数" SortExpression="算数" />
<asp:BoundField DataField="社会" HeaderText="社会" SortExpression="社会" />
</Columns>
</asp:GridView>
<aspbjectDataSource ID="ObjectDataSource3" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetDataBy"
TypeName="DataSet1TableAdapters.DataTable1TableAdapter">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="Param1"
PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="DropDownList2" Name="Param2"
PropertyName="SelectedValue" Type="String" />
</SelectParameters>
</aspbjectDataSource>
</p>
<div>
</div>
</form>
</body>
</html>
そこに問題があるのかどうか分かりませんが、ObjectDataSource でなく
SqlDataSource を使った例をアップしておきます。
接続文字列(下記では ConnectionStrings:Northwind)、フィールド名
(下記では「名前」「クラス」 )、テーブル名(下記では table)は実
際にあわせて書き直してください。
<asp:SqlDataSource ID="SqlDataSource1" <asp:SqlDataSource ID="SqlDataSource2"
runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="SELECT DISTINCT [名前] FROM [table]">
</asp:SqlDataSource>
<asp:DropDownList ID="DropDownList1"
runat="server"
AppendDataBoundItems="True"
DataSourceID="SqlDataSource1"
DataTextField="名前"
DataValueField="名前">
<asp:ListItem Value="ALL">ALL</asp:ListItem>
</asp:DropDownList>
runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="SELECT DISTINCT [クラス] FROM [table]">
</asp:SqlDataSource>
<asp:DropDownList ID="DropDownList2"
runat="server"
AppendDataBoundItems="True"
DataSourceID="SqlDataSource2"
DataTextField="クラス"
DataValueField="クラス">
<asp:ListItem Value="ALL">ALL</asp:ListItem>
</asp:DropDownList>
WHERE (? = 'ALL') AND (? = 'ALL') OR
(? = 'ALL') AND (クラス = ?) OR
(? = 'ALL') AND (名前 = ?) OR
(クラス = ?) AND (名前 = ?)
と指定し、ObjectDataSourceを
DropDownList1、DropDownList2、DropDownList1、DropDownList2、DropDownList2、
DropDownList1、DropDownList2、DropDownList1で
指定し、思うような操作ができるようになったのですが
このままでは全てのデータからのDropDownListの指定条件が抽出されますが
これを国語が100点、80点、60点のもののみのデータ表示という条件を
付け加えるには如何したらいいのでしょうか?
(kokugo = 100) OR (kokugo = 80) OR (kokugo = 600) AND を付け加えてみたりとしてみたのですが
ALLの場合のみよく、DropDownListを指定するとうまく動作しなくなります。
どのようにしたら指定ができるのでしょうか?
最終的にどのようなコントロールを使ったのか分かりませんが・・・
DropDownList のデータソースは AccessDataSource のまま変更しておらず、GridView
のデータソース ObjectDataSource の SelectMethod に指定したGetDataBy メソッドの
WHERE 句を書き換えているのでしょうか?
であれば、たぶん、論理演算子(NOT、AND、OR)の優先順位が考えられていないことが
うまくいかない原因でしょう。
優先順位は、高い方から NOT、AND、OR です。カッコを使用することによって、検索条
件におけるこれらの優先順位を変更することができます。以下のようにしてみたらどう
なるか、試してみてください。(未検証です。DB がないので)
WHERE
( (kokugo = 100) OR (kokugo = 80) OR (kokugo = 60) )
AND
( (? = 'ALL') AND (? = 'ALL') OR
(? = 'ALL') AND (クラス = ?) OR
(? = 'ALL') AND (名前 = ?) OR
(クラス = ?) AND (名前 = ?) )
> いつも、データセットでGetDataBy メソッドの WHERE 句をフィルタを使用して書き換えて
> ObjectDataSourceで使用しているのですが、
> AccessDataSourceやSQLDataSourceを使ったほうがいいのでしょうか???
どちらを使ったほうが簡単にできるかということで判断すると、AccessDataSource や
SqlDataSource の方なのでそれを使いました。余計(?)な手間をかけて面倒なこと
をするより、簡単にできたほうがいいですよね? 間違いも少なくなりますし。
自分的には、ウィザードベースでは作れないようなクエリが必要な場合など、
SqlDataSource では無理なときのみ ObjectDataSource を使うのがよいと思っていま
す。
SQL文が以前より上達し、以前はコードは断念しデータセットによるノンコーディングの方法で解決したのですが
書けるようになりましたのでUPさせていただきます。
アドバイスいただいた方にはとても感謝しております。読み返すと、本当に自分がわかっていなかったのがよくわかりました。
親切にお付き合いいただきありがとうございます。コードがかけるようになりました。
<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim conStr As String = ConfigurationManager.ConnectionStrings("project_jobConnectionString").ConnectionString Dim strSQL As String '名前がカラ、性別がカラの時は全部で If DropDownList1.Text = [String].Empty AndAlso DropDownList2.Text = [String].Empty Then strSQL = "SELECT 名前.ID, 名前.名前, 名前.性別, 成績.国語, 成績.数学, 成績.社会 FROM 名前 INNER JOIN 成績 ON 名前.ID = 成績.ID" '名前がカラで性別がカラでない場合 ElseIf DropDownList1.Text = [String].Empty AndAlso DropDownList2.Text <> [String].Empty Then strSQL = "SELECT 名前.ID, 名前.名前, 名前.性別, 成績.国語, 成績.数学, 成績.社会 FROM 名前 INNER JOIN 成績 ON 名前.ID = 成績.ID WHERE (@Param1 = '') OR (名前.性別 = @Param1)" '名前がカラでなく性別がカラの場合 ElseIf DropDownList1.Text <> [String].Empty AndAlso DropDownList2.Text = [String].Empty Then strSQL = "SELECT 名前.ID, 名前.名前, 名前.性別, 成績.国語, 成績.数学, 成績.社会 FROM 名前 INNER JOIN 成績 ON 名前.ID = 成績.ID WHERE (@Param1 = '') OR (名前.名前 = @Param1)" '名前も性別もカラでない場合 Else strSQL = "SELECT 名前.ID, 名前.名前, 名前.性別, 成績.国語, 成績.数学, 成績.社会 FROM 名前 INNER JOIN 成績 ON 名前.ID = 成績.ID WHERE (@Param1 = '') OR (名前.名前 = @Param1) AND (@Param2 = '') OR (名前.性別 = @Param2)" End If Using con As New SqlConnection(conStr) Using cmd As New SqlCommand(strSQL, con) Dim dr As SqlDataReader '名前がカラ、性別がカラの時は全部で If DropDownList1.Text = [String].Empty AndAlso DropDownList2.Text <> [String].Empty Then cmd.Parameters.AddWithValue("@Param1", DropDownList2.Text) '名前がカラでなく性別がカラの場合 ElseIf DropDownList1.Text <> [String].Empty AndAlso DropDownList2.Text = [String].Empty Then cmd.Parameters.AddWithValue("@Param1", DropDownList1.Text) '名前も性別もカラでない場合 Else cmd.Parameters.AddWithValue("@Param1", DropDownList1.Text) cmd.Parameters.AddWithValue("@Param2", DropDownList2.Text) End If con.Open() dr = cmd.ExecuteReader(Data.CommandBehavior.CloseConnection) GridView1.DataSource = dr GridView1.DataBind() dr.Close() End Using End Using End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>無題のページ</title> </head> <body> <form id="form1" runat="server"> <div> 名前<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlDataSource1" DataTextField="名前" DataValueField="名前" AppendDataBoundItems="True"> <asp:ListItem Value="">ALL</asp:ListItem> </asp:DropDownList> 性別<asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource1" DataTextField="性別" DataValueField="性別" AppendDataBoundItems="True"> <asp:ListItem Value="">ALL</asp:ListItem> </asp:DropDownList> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:project_jobConnectionString2 %>" SelectCommand="SELECT DISTINCT * FROM [名前]"></asp:SqlDataSource> <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" /> </div> <asp:GridView ID="GridView1" runat="server"> </asp:GridView> </form> </body> </html>