トップ回答者
Gridviewの行追加/削除

質問
-
環境:ASP.NET4 (VB)
Gridviewに行を追加/削除の方法を教えてください。
SqlDataSourceからGridviewを表示しています。
やりたいことは次の事です。
1.行追加ボタンをクリックすると、編集用レコードが追加される
2.削除ボタンをクリックすると、該当レコードが削除される
ただし、追加/削除とも各ボタンの押下時にデータベースから削除/追加されるわけではなく
更新ボタンをクリックしたときのイベントで処理しようと思ってます。↓[行追加]ボタンをクリックしたときレコード追加
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px" CellPadding="3" DataSourceID="SqlDataSource_test" GridLines="Horizontal"> <AlternatingRowStyle BackColor="#F7F7F7" /> <Columns> <asp:TemplateField HeaderText="球団名"> <ItemTemplate> <asp:DropDownList ID="ddl_kyudan" runat="server" width="150px" DataTextField="kyudan_name" DataValueField="kyudan_id" AppendDataBoundItems="True" DataSourceID="SqlDataSource_ddl_kyudan" SelectedValue='<%# Eval("kyudan_id") %>'> <asp:ListItem Value=""></asp:ListItem> </asp:DropDownList> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="選手名"> <ItemTemplate> <asp:TextBox ID="txt_Sensyu" runat="server" Text='<%# Eval("sensyu_name")%>'></asp:TextBox> </ItemTemplate> </asp:TemplateField> <asp:ButtonField ButtonType="Button" HeaderText="" Text="削除" CommandName="btn_Sakujo" /> </Columns> <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" /> <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" /> <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" /> <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" /> <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" /> <SortedAscendingCellStyle BackColor="#F4F4FD" /> <SortedAscendingHeaderStyle BackColor="#5A4C9D" /> <SortedDescendingCellStyle BackColor="#D8D8F0" /> <SortedDescendingHeaderStyle BackColor="#3E3277" /> </asp:GridView>
<asp:Button ID="btn_GyoAdd" runat="server" Text="行追加"/><br /><br />
<asp:Button ID="btn_Kousin" runat="server" Text="更新" width="120px"/>
<asp:Button ID="btn_Cancel" runat="server" Text="キャンセル" width="120px" />●やろうとしても出来ない(わからない)こと
1.行追加ボタン「btn_GyoAdd」クリックイベントで行が追加出来ないProtected Sub btn_GyoAdd_Click(sender As Object, e As System.EventArgs) Handles btn_GyoAdd.Click '1行追加 GridView1.Rows.Add() '←これだとコンパイルエラーが発生 End Sub
2.削除ボタン「btn_Sakujo」クリックをGridviewのRowCommandイベントで拾って削除できない(そもそもSelectedIndexの値が取れていないよう)
Protected Sub GridView1_RowCommand(sender As Object, e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand '該当行を削除 If e.CommandName = "btn_Sakujo" Then 'GridView1.Rows.RemoveAt(GridView1.SelectedIndex) 'これだとエラー発生 GridView1.Rows(GridView1.SelectedIndex).Visible = False 'これだと単に非表示になるだけ End If End Sub
PS.球団名と選手名がテレコになっているのはご愛敬で・・・
回答
-
テストコードを書いてみました。時間があまり取れないのでC#、かつコードがあまり綺麗でないことをご了承ください。m(_ _)m
やはりコレクションをかませた方が楽だと思いましたので、そのようにしました。テストコードで使った野菜テーブルは、IDと野菜名だけの単純な構造です。IDは主キーでIDENTITYの指定がしてあります。<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GridViewAllrowEdit.aspx.cs" Inherits="test2010web.GridViewAllrowEdit" %> <!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> </div> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" onrowcommand="GridView1_RowCommand"> <Columns> <asp:TemplateField HeaderText="ID"> <ItemTemplate> <asp:Label ID="ID" runat="server" Text='<%# Eval("ID") %>' /> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="野菜"> <ItemTemplate> <asp:TextBox ID="野菜名" runat="server" Text='<%# Eval("野菜名") %>' /> </ItemTemplate> </asp:TemplateField> <asp:ButtonField ButtonType="Button" Text="削除" CommandName="削除"/> </Columns> </asp:GridView> <asp:Button ID="bttn_追加" runat="server" Text="追加" onclick="bttn_追加_Click" /> <asp:Button ID="bttn_更新" runat="server" onclick="bttn_更新_Click" Text="更新" /> </form> </body> </html>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using test2010web.野菜DataSetTableAdapters; using System.Collections.ObjectModel; namespace test2010web { public partial class GridViewAllrowEdit : System.Web.UI.Page { List<野菜> UIObjects; 野菜TableAdapter adapter; 野菜DataSet.野菜DataTable table; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { UIObjects = new List<野菜>(); adapter = new 野菜TableAdapter(); table = new 野菜DataSet.野菜DataTable(); adapter.Fill(table); FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); Session["adapter"] = adapter; Session["table"] = table; Session["UIObjects"] = UIObjects; } else { adapter = Session["adapter"] as 野菜TableAdapter; table = Session["table"] as 野菜DataSet.野菜DataTable; UIObjects = Session["UIObjects"] as List<野菜>; } } //DataTableからCollectionへコピーする。 private void FromDataTableToCollection() { UIObjects.Clear(); foreach (野菜DataSet.野菜Row row in table.Rows) { if (row.RowState != System.Data.DataRowState.Deleted) UIObjects.Add(new 野菜() { ID = row.id, 野菜名 = row.野菜名}); } Session["UIObjects"] = UIObjects; } //CollectionをDataTableへコピーする。 private void FromCollectionToDataTable() { foreach (var item in UIObjects) { 野菜DataSet.野菜Row row = table.FindByid(item.ID); if (row == null) { row = table.New野菜Row(); row.野菜名 = item.野菜名; table.Rows.Add(row); item.ID = row.id; } else { if (row.野菜名 != item.野菜名)
#if (row.野菜名 != item.野菜名) を追記。
row.野菜名 = item.野菜名; } } Session["table"] = table; } //DataGridViewをCollectionへコピーする。 private void FromDataGridViewToCollection() { UIObjects.Clear(); foreach (GridViewRow row in GridView1.Rows) { int _id = int.Parse(((Label)row.FindControl("ID")).Text); string _野菜名 = ((TextBox)row.FindControl("野菜名")).Text; UIObjects.Add(new 野菜() { ID = _id, 野菜名 = _野菜名 }); } Session["UIObjects"] = UIObjects; } //行の追加 protected void bttn_追加_Click(object sender, EventArgs e) { FromDataGridViewToCollection(); FromCollectionToDataTable(); var row = table.New野菜Row(); row.野菜名 = ""; table.Rows.Add(row); FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); } //行の削除 protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { int rowindex = int.Parse(e.CommandArgument.ToString()); int id = int.Parse(GridView1.DataKeys[rowindex].Value.ToString()); FromDataGridViewToCollection(); FromCollectionToDataTable(); 野菜DataSet.野菜Row row = table.FindByid(id); row.Delete(); Session["table"] = table; FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); } //データベースへ反映 protected void bttn_更新_Click(object sender, EventArgs e) { FromDataGridViewToCollection(); FromCollectionToDataTable(); 空白行削除(); adapter.Update(table); FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); } //空白行を削除 private void 空白行削除() { var items = UIObjects.FindAll(p => p.野菜名 == ""); foreach (野菜 item in items) { 野菜DataSet.野菜Row row = table.FindByid(item.ID); row.Delete(); } } } public class 野菜 { public int ID { get; set; } public string 野菜名 { get; set; } } }
#登録ボタンは更新ボタンという名前の方が好ましいので修正
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2012年8月1日 6:49 追記
- 回答としてマーク とうふちくわ 2012年8月3日 0:01
すべての返信
-
一覧を一通り弄ってから更新ボタンで一気に更新をかけるので、SqlDataSourceではなく、TableAdapterを使用した方が良いでしょう。GridViewへのバインドはDataTableになります。本当は、DataTableを直接バインドするのではなく、何らかのコレクションを間に挟んでこれをバインドするのが望ましいのですが(※1)、単純な仕様の画面であれば利点の割にコーディング量が増えますから、必須ではないでしょう。
追加や削除はGridViewに対して行うのではなく、DataTableに対して行います。その後、更新ボタンを押した際にはTableAdapterのUpdateメソッドを呼び出すだけです。DataTableに追加した際に主キーが-1ずつ増えたり、TableAdapter.Updateメソッド実行後に実際にデータベースに登録した際に採番された主キーの値を取り込む作業なども自動で行ってくれます。(主キー取り込まないと、次にそのレコードの更新ができません)今回は画面のサンプルを見る限り、同時実行制御を行わなくても良さそうです。もし、必要な場合でもTableAdapterが自動で行うようにオプションを選ぶことが可能です。
※1 画面へのバインドやプログラムで操作するためにコレクションを用い、TableAdapter(DataSet, DataTableなど)はデータベースの操作ツールに徹します。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
trapemiyaさんご回答ありがとうございます。
TableAdapterを使ってDataSetを作りまして、行の追加が出来るようになりました。
Protected Sub btn_GyoAdd_Click(sender As Object, e As System.EventArgs) Handles btn_GyoAdd.Click '1行追加処理 'セッションからDataSetを取得 Dim ds As Data.DataSet = Session("DataSet") Dim dr As DataRow dr = ds.Tables(0).NewRow dr("kyudan_id") = "" dr("sensyu_name") = "" ds.Tables(0).Rows.Add(dr) 'Gridviewを描画 GridView1.DataSource = ds GridView1.DataBind() End Sub
あるサイトを参考に作成してみましたが、行は追加されるものの当然ながら?、行を追加すると編集中の選手名などは元に戻ってしまいます。編集したの内容をDataSetに反映させてから「Rows.Add()」しなければならないのだろうと推測しますが、そのやり方を見つけられませんでした。どのような方法があるのでしょうか?
- 編集済み とうふちくわ 2012年7月31日 8:05
-
> ただし、追加/削除とも各ボタンの押下時にデータベースか
> ら削除/追加されるわけではなく更新ボタンをクリックした
> ときのイベントで処理しようと思ってます。ステートレスな Web アプリではそれは無理・・・とまでは言
いませんが、とても難しいことであるのは認識されているで
しょうか?一括更新だけであれば、以下のページのようにすれば、それほ
ど難しいことではないです。チュートリアル : GridView Web サーバー コントロールにバ
インドされた行の一括更新を実行する
http://msdn.microsoft.com/ja-jp/library/aa992036%28v=vs.100%29.aspxただし、上記に加えて、レコードの追加と削除も[更新]ボタ
ンクリックでまとめて一度にやろうとすると、とたんに敷居が
高くなります。直近のレスにあった、> 行を追加すると編集中の選手名などは元に戻ってしまいます。
というのがその一例です。
Windows アプリケーションでは難しいことではないですが、Web
アプリケーションでは話が違います。自分的にはお勧めできませ
ん。Web アプリケーションでできることできないことをよく見極め
て(やればできるではなく現実的にです。Session を使うのは
メモリ枯渇の問題で現実的ではないかもしれません)、よく考
えてプランを作ることをお勧めします。 -
テストコードを書いてみました。時間があまり取れないのでC#、かつコードがあまり綺麗でないことをご了承ください。m(_ _)m
やはりコレクションをかませた方が楽だと思いましたので、そのようにしました。テストコードで使った野菜テーブルは、IDと野菜名だけの単純な構造です。IDは主キーでIDENTITYの指定がしてあります。<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GridViewAllrowEdit.aspx.cs" Inherits="test2010web.GridViewAllrowEdit" %> <!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> </div> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" onrowcommand="GridView1_RowCommand"> <Columns> <asp:TemplateField HeaderText="ID"> <ItemTemplate> <asp:Label ID="ID" runat="server" Text='<%# Eval("ID") %>' /> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="野菜"> <ItemTemplate> <asp:TextBox ID="野菜名" runat="server" Text='<%# Eval("野菜名") %>' /> </ItemTemplate> </asp:TemplateField> <asp:ButtonField ButtonType="Button" Text="削除" CommandName="削除"/> </Columns> </asp:GridView> <asp:Button ID="bttn_追加" runat="server" Text="追加" onclick="bttn_追加_Click" /> <asp:Button ID="bttn_更新" runat="server" onclick="bttn_更新_Click" Text="更新" /> </form> </body> </html>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using test2010web.野菜DataSetTableAdapters; using System.Collections.ObjectModel; namespace test2010web { public partial class GridViewAllrowEdit : System.Web.UI.Page { List<野菜> UIObjects; 野菜TableAdapter adapter; 野菜DataSet.野菜DataTable table; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { UIObjects = new List<野菜>(); adapter = new 野菜TableAdapter(); table = new 野菜DataSet.野菜DataTable(); adapter.Fill(table); FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); Session["adapter"] = adapter; Session["table"] = table; Session["UIObjects"] = UIObjects; } else { adapter = Session["adapter"] as 野菜TableAdapter; table = Session["table"] as 野菜DataSet.野菜DataTable; UIObjects = Session["UIObjects"] as List<野菜>; } } //DataTableからCollectionへコピーする。 private void FromDataTableToCollection() { UIObjects.Clear(); foreach (野菜DataSet.野菜Row row in table.Rows) { if (row.RowState != System.Data.DataRowState.Deleted) UIObjects.Add(new 野菜() { ID = row.id, 野菜名 = row.野菜名}); } Session["UIObjects"] = UIObjects; } //CollectionをDataTableへコピーする。 private void FromCollectionToDataTable() { foreach (var item in UIObjects) { 野菜DataSet.野菜Row row = table.FindByid(item.ID); if (row == null) { row = table.New野菜Row(); row.野菜名 = item.野菜名; table.Rows.Add(row); item.ID = row.id; } else { if (row.野菜名 != item.野菜名)
#if (row.野菜名 != item.野菜名) を追記。
row.野菜名 = item.野菜名; } } Session["table"] = table; } //DataGridViewをCollectionへコピーする。 private void FromDataGridViewToCollection() { UIObjects.Clear(); foreach (GridViewRow row in GridView1.Rows) { int _id = int.Parse(((Label)row.FindControl("ID")).Text); string _野菜名 = ((TextBox)row.FindControl("野菜名")).Text; UIObjects.Add(new 野菜() { ID = _id, 野菜名 = _野菜名 }); } Session["UIObjects"] = UIObjects; } //行の追加 protected void bttn_追加_Click(object sender, EventArgs e) { FromDataGridViewToCollection(); FromCollectionToDataTable(); var row = table.New野菜Row(); row.野菜名 = ""; table.Rows.Add(row); FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); } //行の削除 protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { int rowindex = int.Parse(e.CommandArgument.ToString()); int id = int.Parse(GridView1.DataKeys[rowindex].Value.ToString()); FromDataGridViewToCollection(); FromCollectionToDataTable(); 野菜DataSet.野菜Row row = table.FindByid(id); row.Delete(); Session["table"] = table; FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); } //データベースへ反映 protected void bttn_更新_Click(object sender, EventArgs e) { FromDataGridViewToCollection(); FromCollectionToDataTable(); 空白行削除(); adapter.Update(table); FromDataTableToCollection(); GridView1.DataSource = UIObjects; GridView1.DataBind(); } //空白行を削除 private void 空白行削除() { var items = UIObjects.FindAll(p => p.野菜名 == ""); foreach (野菜 item in items) { 野菜DataSet.野菜Row row = table.FindByid(item.ID); row.Delete(); } } } public class 野菜 { public int ID { get; set; } public string 野菜名 { get; set; } } }
#登録ボタンは更新ボタンという名前の方が好ましいので修正
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2012年8月1日 6:49 追記
- 回答としてマーク とうふちくわ 2012年8月3日 0:01
-
trapemiyaさん SurferOnWwwさん ご回答ありがとうございます。
初心者の泥臭いコードで恐縮ですが、行の追加/削除処理を書いてみました。
Protected Sub rowUpdate(mode As String, delindex As Integer) '行の追加/削除を行う 'mode:Ins 1行追加/Del 1行削除 'delindex:削除するインデックス番号 '描画されているGridView1の内容をDataTableに格納する Dim dr As DataRow Dim ds As New DataTable ds.Columns.Add("kyudan_id", GetType(Integer)) ds.Columns.Add("sensyu_name", GetType(String)) Dim gv As GridView = GridView1 For i = 0 To gv.Rows.Count - 1 '削除モードかつ削除インデックス番号のレコードはDataTableに格納しない If mode = "Ins" OrElse (mode = "Del" AndAlso delindex <> i) Then dr = ds.NewRow '球団ID Dim kyudan As DropDownList = gv.Rows(i).FindControl("ddl_kyudan") dr("kyudan_id") = kyudan.SelectedValue '選手名 Dim sensyu As TextBox = gv.Rows(i).FindControl("txt_Sensyu") dr("sensyu_name") = sensyu.Text ds.Rows.Add(dr) End If Next '追加モードのときは空行を格納 If mode = "Ins" Then dr = ds.NewRow dr("kyudan_id") = "0" dr("sensyu_name") = "" ds.Rows.Add(dr) End If ds.AcceptChanges() gv.DataSource = ds gv.DataBind() End Sub
trapemiyaさんコードまで書いて頂いてありがとうございます。VBにコンバートして読ませて頂こうと思います。
- 編集済み とうふちくわ 2012年8月1日 8:04
-
> 行の追加/削除処理を書いてみました。
それで作った DataTable では DB の更新ができないと思います。
以下のページの図1、図2を見ていただくと、どういった操作が必要
なのか分かります。DB 設計者のための明解 ADO.NET 第 1 回
http://msdn.microsoft.com/ja-jp/events/dd231281.aspx
上のページの図1の操作を行うためには、最初に DataTable に Fill
してインスタンスを作り(メモリに保持し)、DataTable のインスタ
ンスに対して行削除/追加/修正等を行う必要があります。しかしながら、DataTable のインスタンスを保持して、それを操作す
るというのは、Web アプリケーションではかなり無理があります。少
なくとも、Windows アプリケーションのようにウィザードでコードを
一行も書かずに作ることはできません。> 行を追加すると編集中の選手名などは元に戻ってしまいます。
ということに対応しようとすると、DataTable をセッションに保持し
て、個々の UI へのユーザー入力が完了するたびにサーバーにユーザ
ー入力を送信し、DataTable を書き換えるという操作が必要です。それは、やろうと思えばできないことではないかもしれませんが、現
実的・実用的かを考えると、自分はそうではないと思います。- 編集済み SurferOnWww 2012年8月1日 13:15 誤字訂正
-
それは、やろうと思えばできないことではないかもしれませんが、現
実的・実用的かを考えると、自分はそうではないと思います。そう思われる理由は何でしょうか? とうふちくわさんの詳細な仕様要求を聞いていない状況でそう思われていますから、その理由はどのようなケースでも100%当てはまるということでしょうか?
私にはそうは思えず、最終的には仕様要求、用意できるハードウエアなどで現実的・実用的かが決まると思います。私はこのスレッドでとうふちくわさんの質問に対する解決方法を単に提案しているだけで、それが現実的・実用的であるかまでは考えていません。気が付いたことは提案しますが、システム開発を請け負っているわけではありませんので、最終的にシステムとして現実的・実用的なのかまでは考えておらず、単に技術的解決策を示しているだけです。もし、システムとして実際に稼働するところまで考えるのであれば、例えば、開発工数が増えてまで一括更新にこだわる必要は無く、通常のGridViewの動作ではダメなのですか?と提案したり、DataTableやコレクションが巨大になる場合、SessionやViewStateに保存した場合のWebサーバーへの負担等を含め、総合的に判断すると思います。
ただ、私は既存の機能で満足しない前向きなとうふちくわさんのチャレンジ精神は好きです。また、一括で更新しなければならない場合が存在することも事実です。全体で整合性が取れた段階でデータベースへ保存せず、1件ずつ操作する度に保存した場合、データベース上で整合性が取れていない状態が発生します。例えば振替伝票などを考えると、貸借のバランスが取れていない状態がデータベースに存在することは好ましいことではありません。とうふちくわさんの詳細な仕様要求はわかりませんが、そのような場合は一括更新に拘っても良いとおもいます。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2012年8月2日 0:56
-
> そう思われる理由は何でしょうか? とうふちくわさんの詳
> 細な仕様要求を聞いていない状況でそう思われていますから、
> その理由はどのようなケースでも100%当てはまるという
> ことでしょうか?一括更新をするために払う開発工数増大/保守性低下というコスト
がペイするかどうか正しく理解してうえでやっているのか、
回答者さんが当方のレスの答えてくれてないので分かりま
せんが、たぶん理解してないと思うからちょっとしつこく言って
います。まぁ、大きなお世話かもしれませんが。今回の例(あくまで例かもしれませんが)では、どう見ても一括
更新が絶対に必要ということはないと思います。であれば、一括
更新を実現するために、Web アプリはステートレスという事実に
逆らってまで機能を実装して、開発工数増大/保守性低下を招くの
は、現実的ではないと思います。実用的かどうかはセッションに保持するデータのサイズと運用環
境にもよりますが、大きなサイズのデータを InProc モードで保
持するのは、メモリの枯渇の問題があると思います。リサイクル
による消失の問題もあります。実際の運用上は StateServer、SQLServer モードを使うケースが
多いようですが、その場合、データのサイズが大きいとシリアル
化のためのオーバーヘッドが無視できなくなります。> 行を追加すると編集中の選手名などは元に戻ってしまいます。
ということに対応するために、個々の UI へのユーザー入力が完
了するたびにサーバーにユーザー入力を送信し、セッションデー
タのストアにアクセスしてシリアライズ/デシリアライズを繰り返
してセッションデータを書き換えるという操作は結構重いのでは
ないでしょうか。
なお、「どのようなケースでも100%当てはまる」などとは一言
も言ってません。お客さんの要求が絡むと話は違でしょう。また、
趣味・勉強のためということであれば、これも話は別です。また、データの整合性の問題ですが、今回の例では関係なさそうで
す。もし、整合性の問題があるとすると、全行一括更新などするの
は要求に逆行していて、反対に、整合性を保てる範囲に限定し、そ
の部分のみトランザクションに束ねて更新をかけるということにな
ると思います。
何にせよ、基本的に、ASP.NET のサーバーコントロールに標準で備
わっている機能の範囲で実装することをまず考えるべきだというの
が自分の意見です。
- 編集済み SurferOnWww 2012年8月2日 13:24 誤字訂正
-
trapemiyaさん SurferOnWwwさん ご回答ありがとうございます。
なんかいろいろと申し訳ありませんでした。。。
今回の質問は、こんなUIを実現したいけどASP.NETではどんなやりかたをするのだろうという勉強の趣旨でした。
更新ボタンをクリックした後のサーバーサイドの処理はUPDATEの処理が実行されるわけではなく、今回のケースではユーザー「山田太郎」のお気に入り球団データを一旦全権DELETEしGridview1の内容をINSERTするようなことを考えました。
> 何にせよ、基本的に、ASP.NET のサーバーコントロールに標準で備
> わっている機能の範囲で実装することをまず考えるべきだというの
> が自分の意見です。工数/保守性を考えると私も同じように考えます。PHPやPerlでゴリゴリとコーディングすることばかりやっていましたが、最近ASP.NETを勉強し始めたところ、これを使いこなせたらめっちゃ生産性が向上するのではと感動していたところです。(その反面、まだまだ理解がたりないせいかチュートリアルとかやっているとあまりにもあっけなくいろんなことが出来てしまうので、裏でASP.NETさんは何をやらかしているのだろうとか、出力されるHTMLソースがすごいことになっているので不安になったりもします)今回質問したケースで、もしかしたら鉄板の手法があるのではないかなと期待しての質問でした。
trapemiyaさん、SurferOnWwwさん貴重なアドバイス・ご回答、本当にありがとうございました。
-
裏でASP.NETさんは何をやらかしているのだろうとか、出力されるHTMLソースがすごいことになっているので不安になったりもします)今回質問したケースで、もしかしたら鉄板の手法があるのではないかなと期待しての質問でした。
そういう趣旨だったんですね。鉄板の手法があるかと言えばないと思いますし、おそらくASP.NETで一括更新を実装している例はかなり少ないと思います。ただ、どのようにデータベースとやり取りをしているかを正しく理解することが大切です。それができていれば、一括更新のような応用も可能です。SqlDataSourceにしても、TableAdapterにしても、Entity Frameworkなどにしても、全てADO.NETが根底にあります。言い換えれば、それらはADO.NETを知らなくてもADO.NETを楽に使うことを目的としたラッパーとも言えるでしょう。よって、特殊なことをしようとした場合は、ADO.NETの知識が必要になることも覚えておいて下さい。
そして、コントロールに何がバインドしているのかを意識することが大切です。自分で意識しなければほとんどの場合はDataViewがバインドしています。DataTableを直接バインドしても、DataViewがバインドするようになっています。SqlDataSourceを使った場合もDataViewがバインドするようになっています。このように裏で自動的にDataViewを用意してくれて、それがバインドする仕組みによって、簡単にバインドしたコントロールを実現できるようになっています。しかし、簡単なだけに応用が効きません。ですから、私は今回はDataViewを使わず、独自に用意したコレクションをバインドさせたのです。
ASP.NETの場合は既に出ているように少し事情が違いますから、独自に用意したコレクションをバインドすることはあまりないのではないかと思います。しかし、WPFなどでは、私はほとんどの場合でコレクションをバインドさせています。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/