トップ回答者
EntityDataSource + ControlParameter + DropDownList の組み合わせで ListItem が増える

質問
-
http://bbs.wankuma.com/index.cgi?mode=al2&namber=51441 で質問していた件ですが、こちらに移動させて頂きます。
環境は VS2008 SP1 C# です。
以下のソースで、ページの初期表示時に titleList に同じデータが2つずつ表示されています。
titleList の AppendDataBoundItems を true にするとさらに1組増えます。
コードビハインドには何も書いていません。
データベースは SQL Server 2008 R2 Developer 上の pubs です。
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=06616212-0356-46a0-8da2-eebc53a68034
一度 publishers の選択を変えて、また初期状態に戻すと、正常に(重複なく)表示されます。
titleList を ListBox や GridView に変えると再現しません。
titlesDataSource の WhereParameters を削除したり、↓のように固定値にしても発生しなくなります。<asp:EntityDataSource ID="titlesDataSource" runat="server" ConnectionString="name=PubsEntities" DefaultContainerName="PubsEntities" EntitySetName="titles" Where="it.publishers.pub_id=@pub_id"> <WhereParameters> <asp:Parameter Name="pub_id" Type="String" DefaultValue="0736" /> </WhereParameters> </asp:EntityDataSource>
または
<asp:EntityDataSource ID="titlesDataSource" runat="server" ConnectionString="name=PubsEntities" DefaultContainerName="PubsEntities" EntitySetName="titles" Where="it.publishers.pub_id='0736'"> </asp:EntityDataSource>
どなたか解消方法をご存知でしたら教えて頂けませんでしょうか。
よろしくお願いいたします。<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="eds._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:DropDownList ID="publisherList" runat="server" AutoPostBack="true" DataSourceID="publishersDataSource" DataTextField="pub_name" DataValueField="pub_id"> </asp:DropDownList> <asp:DropDownList ID="titleList" runat="server" DataSourceID="titlesDataSource" DataTextField="title" DataValueField="title_id"> </asp:DropDownList> <asp:EntityDataSource ID="publishersDataSource" runat="server" ConnectionString="name=PubsEntities" DefaultContainerName="PubsEntities" EntitySetName="publishers"> </asp:EntityDataSource> <asp:EntityDataSource ID="titlesDataSource" runat="server" ConnectionString="name=PubsEntities" DefaultContainerName="PubsEntities" EntitySetName="titles" AutoGenerateWhereClause="True"> <WhereParameters> <asp:ControlParameter Name="publishers.pub_id" ControlID="publisherList" PropertyName="SelectedValue" /> </WhereParameters> </asp:EntityDataSource> </div> </form> </body> </html>
αετος(aetos)
Microsoft MVP for Visual C++ Feb 2008 - Jun 2011
http://www.aetosfolia.jp/
http://aetosfolia.spaces.live.com/
Microsoft Certified Technology Specialist
Microsoft Certified Associate
I bing. U bing ?
回答
-
EntityDataSource は使ったことがない自分がレスするのもなんですが、気がついた
点をレスします。一応目的の動作をするまで作ってみましたが、その過程で「titleList に同じデータ
が2つずつ表示されています」ということは一度もなかったです。自分が作ったコードと aetos さんのコードを見比べてみてもほとんど同じですし、ど
こに問題があるか分かりません。(自分が作ったコードは下にアップしておきます)違うのは、最初の表示のときに DropDownList.DataBind をしている点です(こうし
ないと、最初の表示で DropDownList.SelectedValue が反映されない)。これがなく
ても「titleList に同じデータが2つずつ表示されています」ということはないです
が、一度試してみてください。その他、ADO.NET Entity Data Model (Model.edmx) がどのように作られているか不明
ですが、それが異なるためかもしれませんね。ところで、何故 EntityDataSource を使っているのでしょうか? DropDownList を使
ってこのようなことをするだけなら、何らメリットはなさそうな感じです。SqlDataSource を使う方がはるかに簡単かつ確実でいいと思うのですが。
<%@ Page Language="C#" %>
<%@ Register Assembly="System.Web.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Namespace="System.Web.UI.WebControls" TagPrefix="asp" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// 何故かこれがないと、最初の表示がうまくいかない。
DropDownList1.DataBind();
DropDownList2.DataBind();
}
}
</script><html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:EntityDataSource ID="EntityDataSource1"
runat="server"
ConnectionString="name=PUBSEntities2"
DefaultContainerName="PUBSEntities2"
EntitySetName="publishers">
</asp:EntityDataSource>
<asp:DropDownList ID="DropDownList1"
runat="server"
AutoPostBack="True"
DataSourceID="EntityDataSource1"
DataTextField="pub_name"
DataValueField="pub_id">
</asp:DropDownList>
<br />
<asp:EntityDataSource ID="EntityDataSource2"
runat="server"
ConnectionString="name=PUBSEntities2"
DefaultContainerName="PUBSEntities2"
EntitySetName="titles"
AutoGenerateWhereClause="True">
<WhereParameters>
<asp:ControlParameter
ControlID="DropDownList1"
Name="publishers.pub_id"
PropertyName="SelectedValue" />
</WhereParameters>
</asp:EntityDataSource>
<asp:DropDownList ID="DropDownList2"
runat="server"
DataSourceID="EntityDataSource2"
DataTextField="title"
DataValueField="title_id">
</asp:DropDownList>
</div>
</form>
</body>
</html>- 回答としてマーク αετος 2010年7月12日 3:13
すべての返信
-
EntityDataSource は使ったことがない自分がレスするのもなんですが、気がついた
点をレスします。一応目的の動作をするまで作ってみましたが、その過程で「titleList に同じデータ
が2つずつ表示されています」ということは一度もなかったです。自分が作ったコードと aetos さんのコードを見比べてみてもほとんど同じですし、ど
こに問題があるか分かりません。(自分が作ったコードは下にアップしておきます)違うのは、最初の表示のときに DropDownList.DataBind をしている点です(こうし
ないと、最初の表示で DropDownList.SelectedValue が反映されない)。これがなく
ても「titleList に同じデータが2つずつ表示されています」ということはないです
が、一度試してみてください。その他、ADO.NET Entity Data Model (Model.edmx) がどのように作られているか不明
ですが、それが異なるためかもしれませんね。ところで、何故 EntityDataSource を使っているのでしょうか? DropDownList を使
ってこのようなことをするだけなら、何らメリットはなさそうな感じです。SqlDataSource を使う方がはるかに簡単かつ確実でいいと思うのですが。
<%@ Page Language="C#" %>
<%@ Register Assembly="System.Web.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Namespace="System.Web.UI.WebControls" TagPrefix="asp" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// 何故かこれがないと、最初の表示がうまくいかない。
DropDownList1.DataBind();
DropDownList2.DataBind();
}
}
</script><html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:EntityDataSource ID="EntityDataSource1"
runat="server"
ConnectionString="name=PUBSEntities2"
DefaultContainerName="PUBSEntities2"
EntitySetName="publishers">
</asp:EntityDataSource>
<asp:DropDownList ID="DropDownList1"
runat="server"
AutoPostBack="True"
DataSourceID="EntityDataSource1"
DataTextField="pub_name"
DataValueField="pub_id">
</asp:DropDownList>
<br />
<asp:EntityDataSource ID="EntityDataSource2"
runat="server"
ConnectionString="name=PUBSEntities2"
DefaultContainerName="PUBSEntities2"
EntitySetName="titles"
AutoGenerateWhereClause="True">
<WhereParameters>
<asp:ControlParameter
ControlID="DropDownList1"
Name="publishers.pub_id"
PropertyName="SelectedValue" />
</WhereParameters>
</asp:EntityDataSource>
<asp:DropDownList ID="DropDownList2"
runat="server"
DataSourceID="EntityDataSource2"
DataTextField="title"
DataValueField="title_id">
</asp:DropDownList>
</div>
</form>
</body>
</html>- 回答としてマーク αετος 2010年7月12日 3:13
-
追試ありがとうございます。
再現手順を詳細に書いてみます。
なお、DBはpubsが利用可能になっているものとします。- VS2008 で新規プロジェクトを作成します。
[Visual C#] > [Web] > [ASP.NET Web アプリケーション] です。 - プロジェクトに [ADO.NET Entity Data Model] を追加します。
[データベースから生成] > [pubs] を選び、テーブルで publishers と titles を選択します。
一度プロジェクトをビルドします。 - フォームに DropDownList を2つ、EntityDataSource を2つ配置します。
DropDownListのIDはそれぞれ publisherList、titleList とします。
EntityDataSourceのIDはそれぞれ publishersDataSource、titlesDataSource とします。 - publishersDataSource のデザイナメニューで [データ ソースの構成] を選びます。
名前付き接続は pubsEntities 、EntitySetName は publishers とします。あとはデフォルトです。
同様に titlesDataSource も構成します。EntitySetName が titles になる以外は同じです。 - titlesDataSource のプロパティで Where の右側の ... ボタンをクリックします。
[指定されたパラメータを基に Where 式を自動生成する] をチェックします。
[パラメータの追加] ボタンを押し、名前を publishers.pub_id、パラメータソースを Control、ControlID を publisherList とします。 - publisherList のデザイナメニューで [データ ソースの選択] を選びます。
データソースは publishersDataSource、表示するデータ フィールドは pub_name、値のデータフィールドは pub_id です。
また、デザイナメニューから [AutoPostBack を有効にする] をチェックします。
同様に titlesList も構成します。
データソースは titlesDataSource、表示するフィールドは title、値のフィールドは title_id です。
こちらは AutoPostBack は有効にしません。 - デバッグ実行します。
手順は以上です。コードは一切記述しておらず、すべて IDE での操作です。
.cs も .aspx も手作業では一文字たりともいじっていません。この状態で、ブラウザ上では New Moon Books と You Can Combat Compurer Stress! が選択されています。
titleList を見ると、You Can ... から Emotional Security ... までが2組表示されています。
publishers で他のデータを選んでもそのようなことはなく、また、再び New Moon Books を選ぶと、やはり重複はありません。違うのは、最初の表示のときに DropDownList.DataBind をしている点です(こうし
ないと、最初の表示で DropDownList.SelectedValue が反映されない)。これがなく
ても「titleList に同じデータが2つずつ表示されています」ということはないです
が、一度試してみてください。これを試してみたところ解消しました。
publishersList の DataBind だけでも大丈夫でした。
ただ、こちらでは DataBind しなくても最初からデータは表示されています。また、フォームに Label と Button を置き、以下のようなコードを加えてみました。
protected void Button1_Click(object sender, EventArgs e) { Label1.Text = (publisherList.SelectedItem == null ? "null" : publisherList.SelectedItem.Text) + ", " + (titleList.SelectedItem == null ? "null" : titleList.SelectedItem.Text); }
SqlDataSource を使う方がはるかに簡単かつ確実でいいと思うのですが。
まぁ SqlDataSource でもいいのですが…問題はとあるプロジェクトで発生しておりまして、そのプロジェクトでEDMを使うということになっているので、EntityDataSource かなぁ、と。特に考えもなくw
αετος(aetos)
Microsoft MVP for Visual C++ Feb 2008 - Jun 2011
http://www.aetosfolia.jp/
http://aetosfolia.spaces.live.com/
Microsoft Certified Technology Specialist
Microsoft Certified Associate
I bing. U bing ? - VS2008 で新規プロジェクトを作成します。
-
先のレスで「その過程で『titleList に同じデータが2つずつ表示されています』という
ことは一度もなかったです。」と書きましたが、見間違いでした。すみません。よく見てみれば、DataBind しない場合、titles の DropDownList には You Can Combat
Computer Stress! から Emotional Security: New Algorithm までの5項目が繰り返し2
回表示されていました。publishers の方の DropDownList には New Moon Books が選択され、中身も期待通り各
項目が一つずつ表示されていました。最初の表示で DataBind しない場合は、aetos さんの結果と同じになっていたようです。
DataBind の方も、両方の DropDownList で行う必要はなく、aetos さんが試された結果
と同様に、publishers の方の DropDownList だけ DataBind すれば OK でした。