none
TableAdapterを使ったGridViewで空のテーブルにデータを登録するコードが動かない(更新できない) RRS feed

  • 質問

  • 下記ページ「毎日のデータを入力するには?」からの続きになります。

    http://social.msdn.microsoft.com/Forums/ja-JP/aspnetja/thread/29121f72-2fba-4ef9-8543-cb46383a5ca6?prof=required

    環境 VS2010 VB SQLSERVER2008 ASP.NET4

    下記SQLです

    SELECT            tbl_shop_machine.shop_machineID, ISNULL(tbl1.daytimeindex, 0) as daytimeindex, tbl_shop.shop_name, tbl_machine.machine_name, ISNULL(tbl1.men, 0) as men, tbl1.inputday, 
                            ISNULL(tbl1.timeID, '') as timeID
    FROM              tbl_shop_machine LEFT OUTER JOIN
                            tbl1 ON tbl1.shop_machineID = tbl_shop_machine.shop_machineID INNER JOIN
                            tbl_shop ON tbl_shop.shopID = tbl_shop_machine.shopID INNER JOIN
                            tbl_machine ON tbl_machine.machineID = tbl_shop_machine.machineID
    WHERE             (tbl_shop_machine.shopID = @shopID)

    下記 aspx

        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="shop_machineID">
            <Columns>
                <asp:TemplateField HeaderText="日別時間帯別ID" 
                    SortExpression="daytimeindex">
                    <ItemTemplate>
                        <asp:Label ID="daytimeindex" runat="server" Text='<%# Bind("daytimeindex") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="店舗商品ID" 
                    SortExpression="shop_machineID">
                    <ItemTemplate>
                        <asp:Label ID="shop_machineID" runat="server" Text='<%# Bind("shop_machineID") %>' ></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                            <asp:BoundField DataField="shop_name" HeaderText="店舗名" SortExpression="shop_name" />
                <asp:BoundField DataField="machine_name" HeaderText="商品名" SortExpression="machine_name" />
                <asp:TemplateField HeaderText="使用者数" SortExpression="men">
           <%--         <EditItemTemplate>
                        <asp:Label ID="Label1" runat="server" Text='<%# Eval("使用者数") %>'></asp:Label>
                    </EditItemTemplate>--%>
                    <ItemTemplate>
                        <asp:TextBox ID="men" runat="server" Text='<%# Bind("men") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="inputday" HeaderText="日付" 
                    SortExpression="inputday" />
                <asp:BoundField DataField="timeID" HeaderText="時間帯" ReadOnly="True" 
                    SortExpression="timeID" />
            </Columns>
        </asp:GridView>
     
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="bttn_検索" runat="server" onclick="bttn_検索_Click" Text="検索" />
        <asp:Button ID="bttn_更新" runat="server" onclick="bttn_更新_Click" Text="更新" />

    下記 aspx.vb
    Imports System.Transactions
    Imports System.Data.SqlClient
    Imports DataSet2TableAdapters
    
    Partial Class input_test
        Inherits System.Web.UI.Page
        Private tadapter As DataTable1TableAdapter
        Private table As DataSet2.DataTable1DataTable
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
            If Not IsPostBack Then
                tadapter = New DataTable1TableAdapter()
                table = New DataSet2.DataTable1DataTable()
    
                tadapter.Fill(table, 0)
                'ダミーの検索
                GridView1.DataSource = table
                GridView1.DataBind()
    
                Session("tadapter") = tadapter
                Session("table") = table
            End If
        End Sub
    
        Protected Sub bttn_検索_Click(ByVal sender As Object, ByVal e As EventArgs)
            tadapter = Session("tadapter")
            table = Session("table")
            tadapter.Fill(table, Integer.Parse(DropDownList2.Text))
    
            GridView1.DataSource = table
            GridView1.DataBind()
    
        End Sub
    
        Protected Sub bttn_更新_Click(ByVal sender As Object, ByVal e As EventArgs)
            tadapter = DirectCast(Session("tadapter"), DataTable1TableAdapter)
            table = DirectCast(Session("table"), DataSet2.DataTable1DataTable)
    
            'Dim tranScope As TransactionScope
    
            Using tranScope = New TransactionScope()
                Using connection = New SqlConnection()
                    connection.ConnectionString = tadapter.Connection.ConnectionString
                    connection.Open()
    
                    Dim insertCommand = New SqlCommand("insert into tbl1 (shop_machineID, men) values (@shop_machineID, @men)", connection)
                    insertCommand.Parameters.Add("@shop_machineID", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
    
                    Dim updateCommand = New SqlCommand("update tbl1 set men = @men where (daytimeindex = @daytimeindex)", connection)
                    updateCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    updateCommand.Parameters.Add("@daytimeindex", System.Data.SqlDbType.Int)
    
                    For Each gr As GridViewRow In GridView1.Rows
                        Dim men As Integer = Integer.Parse(DirectCast(gr.FindControl("men"), TextBox).Text)
                        Dim shop_machineID As Integer = Integer.Parse(DirectCast(gr.FindControl("shop_machineID"), Label).Text)
                        Dim daytimeindex As Integer = Integer.Parse(DirectCast(gr.FindControl("daytimeindex"), Label).Text)
    
                        If daytimeindex = 0 Then
                            insertCommand.Parameters("@shop_machineID").Value = shop_machineID
                            insertCommand.Parameters("@men").Value = men
                            insertCommand.ExecuteNonQuery()
                        Else
                            updateCommand.Parameters("@men").Value = men
                            updateCommand.Parameters("@daytimeindex").Value = daytimeindex
                            updateCommand.ExecuteNonQuery()
    
                        End If
                    Next
                End Using
    
                tranScope.Complete()
            End Using
        End Sub
    
    End Class

    デバック時にテーブルに入力をした使用者数(men)の値がtbl1に登録されないのです。

    原因は何でしょうか?


    2012年4月2日 4:39

回答

  • 山本さま、ありがとうございます。

    さて、私の方で動いているコードを以下に載せます。途中で考え方を変えたため、必要のないSession変数が残っていたりしましたが、それらを取り、シンプルにしました。このコードをkazukazu2002 さんの方で試していただき、それでもGridViewのRowsが取得できない(GridView1.Rows.Countが0である)のであれば、これが問題だと思いますので、この問題に絞って新しくスレッドを立てて下さい。スレッドのタイトルは、解決できない点をできるだけ明記するようにして下さい。より的確でより迅速に回答を得るために、短時間で問題点が把握できるように的を絞った質問になるように努力して下さい。そういう意味で、タイトルは非常に重要です。質問の問題点がはっきりしており、それに対する解決策が的確に示されたスレッドは、自然に他の人への財産にもなります。

    現在私が気になっているのは、前回のスレッドも含め、このスレッドが公開デバッグのようになってしまっていることです。多少であれば良いのですが、あまり多くなるとチャットのような形になり、他の人から有益な情報が得られにくくなってしまいます。kazukazu2002 さんに問題切り分けの力を付けてもらいたくて、私もあえて多少は公開デバッグ的に進めてきたところもありますので、kazukazu2002 さんの質問の仕方だけに問題があるわけではありません。kazukazu2002 さんが早く問題を解決されることを願っていますし、kazukazu2002 さんも努力されていることは伝わってきます。
    質問者よし、回答者よし、閲覧者よしの三方よしとなるように、もう少し私も気を配って行きますね。

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="GridViewOuterJoinInput3.aspx.vb" Inherits="test2010webvb.GridViewOuterJoinInput3" %>
     
    <!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">
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="shop_machineID">
            <Columns>
                <asp:TemplateField HeaderText="日別時間帯別ID" 
                    SortExpression="daytimeindex">
                    <ItemTemplate>
                        <asp:Label ID="daytimeindex" runat="server" Text='<%# Bind("daytimeindex") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="店舗商品ID" 
                    SortExpression="shop_machineID">
                    <ItemTemplate>
                        <asp:Label ID="shop_machineID" runat="server" Text='<%# Bind("shop_machineID") %>' ></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                            <asp:BoundField DataField="shop_name" HeaderText="店舗名" SortExpression="shop_name" />
                <asp:BoundField DataField="machine_name" HeaderText="商品名" SortExpression="machine_name" />
                <asp:TemplateField HeaderText="使用者数" SortExpression="men">
           <%--         <EditItemTemplate>
                        <asp:Label ID="Label1" runat="server" Text='<%# Eval("使用者数") %>'></asp:Label>
                    </EditItemTemplate>--%>
                    <ItemTemplate>
                        <asp:TextBox ID="men" runat="server" Text='<%# Bind("men") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="inputday" HeaderText="日付" 
                    SortExpression="inputday" />
                <asp:BoundField DataField="timeID" HeaderText="時間帯" ReadOnly="True" 
                    SortExpression="timeID" />
            </Columns>
        </asp:GridView>
     
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="bttn_検索" runat="server" onclick="bttn_検索_Click" Text="検索" />
        <asp:Button ID="bttn_更新" runat="server" onclick="bttn_更新_Click" Text="更新" />
     
        </form>
    </body>
    </html>
    
    Imports System.Transactions
    Imports System.Data.SqlClient
    Imports test2010webvb.DataSet2TableAdapters
     
    Public Class GridViewOuterJoinInput3
        Inherits System.Web.UI.Page
     
        Protected Sub Page_Load(ByVal sender As ObjectByVal e As EventArgsHandles Me.Load
     
        End Sub
     
        Protected Sub bttn_検索_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable1TableAdapter()
            Dim table = New DataSet2.DataTable1DataTable()
     
            tadapter.Fill(table, Integer.Parse(TextBox1.Text))
     
            GridView1.DataSource = table
            GridView1.DataBind()
     
        End Sub
     
        Protected Sub bttn_更新_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable1TableAdapter()
     
            Using tranScope = New TransactionScope()
                Using connection = New SqlConnection()
                    connection.ConnectionString = tadapter.Connection.ConnectionString
                    connection.Open()
     
                    Dim insertCommand = New SqlCommand("insert into tbl1 (shop_machineID, men) values (@shop_machineID, @men)", connection)
                    insertCommand.Parameters.Add("@shop_machineID", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
     
                    Dim updateCommand = New SqlCommand("update tbl1 set men = @men where (daytimeindex = @daytimeindex)", connection)
                    updateCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    updateCommand.Parameters.Add("@daytimeindex", System.Data.SqlDbType.Int)
     
                    For Each gr As GridViewRow In GridView1.Rows
                        Dim men As Integer = Integer.Parse(DirectCast(gr.FindControl("men"), TextBox).Text)
                        Dim shop_machineID As Integer = Integer.Parse(DirectCast(gr.FindControl("shop_machineID"), Label).Text)
                        Dim daytimeindex As Integer = Integer.Parse(DirectCast(gr.FindControl("daytimeindex"), Label).Text)
     
                        If daytimeindex = 0 Then
                            insertCommand.Parameters("@shop_machineID").Value = shop_machineID
                            insertCommand.Parameters("@men").Value = men
                            insertCommand.ExecuteNonQuery()
                        Else
                            updateCommand.Parameters("@men").Value = men
                            updateCommand.Parameters("@daytimeindex").Value = daytimeindex
                            updateCommand.ExecuteNonQuery()
     
                        End If
                    Next
                End Using
     
                tranScope.Complete()
     
            End Using
        End Sub
     
    End Class

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kazukazu2002 2012年4月3日 6:59
    2012年4月3日 5:47
    モデレータ
  • なるほど。的確な情報をいただいたおかげで謎が解けました。私のコードが簡易であったため、二度続けて更新ボタンを押し、データが二重に登録されてしまったようです。
    更新ボタンを押した後は検索を実行し、最新のdaytimeindexを読み込む必要があります。よって、以下のようにコードを修正すると何度続けて更新ボタンを押しても大丈夫なはずです。(最初はdaytimeindexが0ですからinsert文が発行されてデータベースに新規登録され、その後、検索されて、データベースで採番されたdaytimeindexが読みこまれ、その後、更新ボタンを押すとdaytimeindexが0以外ですから、データベースへ今度はupdate文が実行され、更新になります。これまではいつまでも経ってもdaytimeindexが0なので二重に登録されてしまったわけです。)

    Imports System.Transactions
    Imports System.Data.SqlClient
    Imports test2010webvb.DataSet2TableAdapters
     
    Public Class GridViewOuterJoinInput5
        Inherits System.Web.UI.Page
     
        Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgsHandles Me.Load
     
        End Sub
     
        Protected Sub bttn_検索_Click(ByVal sender As ObjectByVal e As EventArgs)
            検索()
        End Sub
     
        Private Sub 検索()
            Dim tadapter = New DataTable2TableAdapter()
            Dim table = New DataSet2.DataTable2DataTable()
     
            tadapter.Fill(table, DateTime.Parse(TextBox2.Text), Integer.Parse(TextBox1.Text))
     
            GridView1.DataSource = table
            GridView1.DataBind()
        End Sub
     
        Protected Sub bttn_更新_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable1TableAdapter()
     
            Using tranScope = New TransactionScope()
                Using connection = New SqlConnection()
                    connection.ConnectionString = tadapter.Connection.ConnectionString
                    connection.Open()
     
                    Dim insertCommand = New SqlCommand("insert into tbl1 (shop_machineID, men, inputday) values (@shop_machineID, @men, @inputday)", connection)
                    insertCommand.Parameters.Add("@shop_machineID", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@inputday", System.Data.SqlDbType.Date)
     
                    Dim updateCommand = New SqlCommand("update tbl1 set men = @men, inputday = @inputday where (daytimeindex = @daytimeindex)", connection)
                    updateCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    updateCommand.Parameters.Add("@inputday", System.Data.SqlDbType.Date)
                    updateCommand.Parameters.Add("@daytimeindex", System.Data.SqlDbType.Int)
     
                    For Each gr As GridViewRow In GridView1.Rows
                        Dim men As Integer = Integer.Parse(DirectCast(gr.FindControl("men"), TextBox).Text)
                        Dim inputday As DateTime = DateTime.Parse(DirectCast(gr.FindControl("inputday"), TextBox).Text)
                        Dim shop_machineID As Integer = Integer.Parse(DirectCast(gr.FindControl("shop_machineID"), Label).Text)
                        Dim daytimeindex As Integer = Integer.Parse(DirectCast(gr.FindControl("daytimeindex"), Label).Text)
     
                        If daytimeindex = 0 Then
                            insertCommand.Parameters("@shop_machineID").Value = shop_machineID
                            insertCommand.Parameters("@men").Value = men
                            insertCommand.Parameters("@inputday").Value = inputday
                            insertCommand.ExecuteNonQuery()
                        Else
                            updateCommand.Parameters("@men").Value = men
                            updateCommand.Parameters("@inputday").Value = inputday
                            updateCommand.Parameters("@daytimeindex").Value = daytimeindex
                            updateCommand.ExecuteNonQuery()
     
                        End If
                    Next
                End Using
     
                tranScope.Complete()
     
            End Using
     
            検索()
        End Sub
    End Class

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kazukazu2002 2012年4月18日 6:38
    2012年4月17日 4:53
    モデレータ
  • >SQL、aspx、VBも(時間帯)と同じ設定なのですが、なぜかできません。なにを見ればよろしいでしょうか?

    TableAdapterのデータプレビューではうまく見れているということですので、SQL文は問題ありません。となると、そのSQL文のパラメータに何らかの原因でうまく値が渡せていないのだと思います。デバッグ実行して、天気で1以外を選択した時にどのような値がパラメータにセットされているのかをチェックする必要があります。
    デバッグでは問題をどんどん切り分けていき、最終的にどこに間違いがあるのかを突き止める手順で行って下さい。バグの箇所を突き止めるには、大きな単位で絞り込んでいき、だんだん小さな単位に絞り込んで見つけるのが基本です。どこまで正しく動いているのかを順を追って確かめていきましょう。正しく動いていないところが見つかれば、その処理の前のどこかにバグがあるということです。

    #このスレッドも一つの問題が解決すれば次の問題へと移り、どんどん長くなっています。シームレス的なところもあって気持ちはわかりますが、解決の方向性は出ており、現在はバグを取るためのやり取になっている感が強くなっています。この質問が悪いというわけではありませんが、このスレッドのタイトルとは直接関係なくなってきていますので、まだ解決しないようであれば新たにスレッドを立てられた方が良いでしょう。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 山本春海 2012年4月19日 2:25
    2012年4月18日 5:03
    モデレータ

すべての返信

  • 書き忘れかもしれませんが、最後にwhere句が必要です。(ただ、無い場合でも登録できない原因にはなりません)

    select tbl_shop_machine.shop_machineID, ISNULL(tbl1.daytimeindex, 0) as daytimeindex, tbl_shop.shop_name, tbl_machine.machine_name, ISNULL(tbl1.men, 0) as men, tbl1.inputday,
                            ISNULL(tbl1.timeID, '') as timeID
    FROM              tbl_shop_machine LEFT OUTER JOIN
                            tbl1 ON tbl1.shop_machineID = tbl_shop_machine.shop_machineID INNER JOIN
                            tbl_shop ON tbl_shop.shopID = tbl_shop_machine.shopID INNER JOIN
                            tbl_machine ON tbl_machine.machineID = tbl_shop_machine.machineID
    where tbl_shop_machine.shopID = @shopID

    後はおかしなところは見当たりませんでした。念のために同じ名前でテーブルを作成して試してみましたが、問題なく動作しました。
    登録した直後に検索ボタンを押した場合、どうなりますか? 登録されていれば、きちんと値が表示されるはずです。
    SQL server 2008はデータベースファイルとして使用されていませんか? この場合、更新されていないように見えることがあります。以下は、VS2005の例ですがVS2010でも同じです。

    Visual Studio 2005でデータベースの更新が反映されない場合には?[VS 2005のみ]
    http://www.atmarkit.co.jp/fdotnet/dotnettips/532dbfilecopy/dbfilecopy.html


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月2日 10:39
    モデレータ
  • trapemiya様 御返答ありがとうございます。

    >登録した直後に検索ボタンを押した場合、どうなりますか? 登録されていれば、きちんと値が表示されるはずです。

    もとの0が表示されます。

    >SQL server 2008はデータベースファイルとして使用されていませんか?

    よくわからないのですが、ソリューションエクスプローラー上ではなく、サーバーエクスプローラー上にdboを作っています。御呈示いただいたアドレスの中身を見させていただいたのですが、プロパティの出力ディレクトリーにコピーというのは表示されていない為、設定できません。

    何が違うのか、見当もつかない状態です。

    ※追記

    もしかしてと思ったのですが、TableAdapterの構成ウィザードで①SQLステートメントを使用するを選択②テーブルに読み込むデータ(記載分SQL)記入③TableAdapterに追加するメソッド(DataTableにデータを格納するチェック→メソッド名Fill)(DataTableを返すチェック→メソッド名GetData)←この下に更新を直接データベースに送信するためのメソッドを作成する(GenerateDBDirectMethods)←チェックなしがあります。←これかなと思って今から調べます。

    そのあと、’DataTable1’DataTableおよび'DataTable1TableAdapter'は正常に構成されました。(SELECTステートメントは生成されました テーブルマップは生成されました Fillメソッドは生成されました Getメソッドを生成しました)→完了

    の流れで生成しています。 これ自体が間違っているのでしょうか?

    GenerateDBDirectMethods

    はTableAdapterでInsertを使わないので必要ないですよね。すみません

    2012年4月2日 11:41
  • データベースファイルではないようですね。GenerateDBDirectMethodsについてはその通りです。関係ありません。

    私の方では、kazukazu2002さんが提示されているコードそのままで問題なく動作しています。あぁ、一つ変えていました。DropDownListをTextBoxに変えています。まぁ、でもこれは登録・更新時には関係しないところですが・・・
    SQL Serverのテーブルを直接見られて、データが入っていないのでしょうか?


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月3日 0:48
    モデレータ
  • 朝からの御返答ありがとうございます。お手数をおかけしております。

    VS2010上で、サーバーエクスプローラーから、指定しているdboのテーブルフォルダのtbl1からテーブルデータの表示で見ています。テーブル定義だけで、全てNULLになっています。

    他のテーブルは(たとえば商品詳細、店舗詳細)FormViewで登録後、上記の方法でテーブルデータは見れます。

    ちなみにtbl1の定義は

    daytimeindex    主キー int NULL不可

    shop_machineID int NULL不可

    men  int NULL許可

    inputday date NULL許可

    timeID  int NULL許可

    shop_name  nvarchar(100) NULL許可

    machine_name nvarchar(100) NULL許可

    です。

    2012年4月3日 0:57
  • 以下の行でブレークポイントで止め、F11を押した時、どうなりますか?

    For Each gr As GridViewRow In GridView1.Rows

    やはり、End Usingまで飛んでしまいますか? そうであればSQL文が発行されていないように思います。SQL Server Profilerは使ったことがありますか? もし無ければ、以下のようにして起動させて下さい。
    全てのプログラムから、「Microsoft SQL Server 2008」 → 「パフォーマンス ツール」 → 「SQL Server Profiler」で起動してください。起動したら、メニューの「ファイル」から「新しいトレース」を実行し、サーバーへの接続ダイアログが開きますから、そこでサーバーへ接続します。トレースのプロパティの画面が開きますので、そのまま実行ボタンを押して下さい。
    この状態でWebアプリを操作すると、SQL ServerにどのようなSQL文が投げられているのかを見ることができます。最初は検索しますから、select文が発行されているはずです。その後、更新ボタンを押すことにより、本来であればinsert文、update文が発行されるのが見えるはずです。

    また、私がテストで作成したテーブルのCreate文を載せておきます。

    USE [TEST]
    GO

    /****** Object:  Table [dbo].[tbl_shop]    Script Date: 04/03/2012 09:58:19 ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    CREATE TABLE [dbo].[tbl_shop](
     [shopID] [int] NOT NULL,
     [shop_name] [nvarchar](10) NULL,
     CONSTRAINT [PK_tbl_shop] PRIMARY KEY CLUSTERED
    (
     [shopID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    USE [TEST]
    GO

    /****** Object:  Table [dbo].[tbl_machine]    Script Date: 04/03/2012 09:58:36 ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    CREATE TABLE [dbo].[tbl_machine](
     [machineID] [int] NOT NULL,
     [machine_name] [nvarchar](10) NULL,
     CONSTRAINT [PK_tbl_machine] PRIMARY KEY CLUSTERED
    (
     [machineID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    USE [TEST]
    GO

    /****** Object:  Table [dbo].[tbl_shop_machine]    Script Date: 04/03/2012 09:58:51 ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    CREATE TABLE [dbo].[tbl_shop_machine](
     [shop_machineID] [int] NOT NULL,
     [shopID] [int] NULL,
     [machineID] [int] NULL,
     CONSTRAINT [PK_tbl_shop_machine] PRIMARY KEY CLUSTERED
    (
     [shop_machineID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    USE [TEST]
    GO

    /****** Object:  Table [dbo].[tbl1]    Script Date: 04/03/2012 09:57:41 ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    CREATE TABLE [dbo].[tbl1](
     [daytimeindex] [int] IDENTITY(1,1) NOT NULL,
     [shop_machineID] [int] NOT NULL,
     [men] [int] NULL,
     [inputday] [nchar](10) NULL,
     [timeid] [int] NULL,
     CONSTRAINT [PK_tbl1_1] PRIMARY KEY CLUSTERED
    (
     [daytimeindex] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    • 編集済み trapemiyaModerator 2012年4月3日 1:49 (追記)For Each gr As GridViewRow In GridView1.Rows
    2012年4月3日 1:08
    モデレータ
  • SQL Server ProfilerがExpressEditionのためありませんのでSqlExpressProfiler-1.2.1708.7というのがあったのですがこれでも問題ないでしょうか?

    >以下の行でブレークポイントで止め、F11を押した時、どうなりますか?

    どこのことでしょうか?

    2012年4月3日 1:20
  • 申し訳ありません。以下です。

    For Each gr As GridViewRow In GridView1.Rows


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月3日 1:41
    モデレータ
  • >For Each gr As GridViewRow In GridView1.Rows

    にブレークポイントを付けて、F11を押した場合、End Usingまで飛びます。

    2012年4月3日 1:45
  • オペレートですが、まず最初に検索ボタンを押して、GridViewに行が表示されていなければいけません。この表示されている「使用者数」のところに人数を入れて更新ボタンを押しているんですよね?
    そして、ブレークポイントで、For Each gr As GridViewRow In GridView1.Rows で止まった時、GridView1.RowsのCountプロパティを見て下さい。この数がGridViewの行数と一致しているはずですが、いくつになっていますか?


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月3日 1:56
    モデレータ
  • 最初に検索ボックスに 1 を入れ検索ボタン →1件表示 →使用者数に 15 を入れ更新ボタンを押す。

    ブレークポイントで止まった状態で、For Each gr As GridViewRow In GridView1.Rows

    太文字の部分にカーソルを当て、プロパティが表示され、countの部分を見ると、 0 が入っています。

    2012年4月3日 2:03
  • こんにちは、kazukazu2002 さん。

    MSDN フォーラムのご利用ありがとうございます。オペレーターの山本です。
    過去の kazukazu2002 さんのスレッドも含めてなのですが、お願いがあります。

    スレッドの返信数が多くなってくると、追いかけて読むことに労力がいりますし、行き違いが多くなることが多いように思います。
    (また、前回のスレッドのようにレスが長くなるとサーバーからのレスポンスにも時間がかかりますし、環境によってはストレスを感じられる方もいらっしゃるかもしれません。)

    この点については、他の方からもフォーラムでの質問の仕方についてや、スレッドが長くなってしまっている原因などについてアドバイスいただいていると思いますので、もう一度読み直してみてください。
    また、出来る限り kazukazu2002 さんが分からない点を切り分けて、一つの質問として成り立つようであれば別スレッドにしてご質問するようにしていただけるとうれしいです。
    個人的には、ここのところなんとなく話の流れで他の人が投稿しにくくなっているような、入り込みにくいような印象を受けています。
    他の方がスレッドに参加しにくくなると、回答する側には多かれ少なかれ心理的な負担がかかってしまうのではと、個人的にとても心配になってしまいます。

    変な言い方なのですが (ごめんなさい) 、他の方にも是非スレッドに参加する機会を与えてあげてください。(やっぱり変な言い方かな?すみません。)

    そして、有効な情報を得られスレッドを終了させる際には、その投稿に回答としてマークしてくださいね。
    後に同じ問題でスレッドを参照する方にも有効な情報が分かりやすくなりますので、ご協力のほどよろしくお願いします。

    質問者も回答者も、フォーラムを閲覧する側もより快適にフォーラムをご利用いただくため、ご理解のほどよろしくお願いいたします。
    _____________________
    日本マイクロソフト株式会社 フォーラム オペレーター 山本 春海

    2012年4月3日 2:54
  • 山本さま、ありがとうございます。

    さて、私の方で動いているコードを以下に載せます。途中で考え方を変えたため、必要のないSession変数が残っていたりしましたが、それらを取り、シンプルにしました。このコードをkazukazu2002 さんの方で試していただき、それでもGridViewのRowsが取得できない(GridView1.Rows.Countが0である)のであれば、これが問題だと思いますので、この問題に絞って新しくスレッドを立てて下さい。スレッドのタイトルは、解決できない点をできるだけ明記するようにして下さい。より的確でより迅速に回答を得るために、短時間で問題点が把握できるように的を絞った質問になるように努力して下さい。そういう意味で、タイトルは非常に重要です。質問の問題点がはっきりしており、それに対する解決策が的確に示されたスレッドは、自然に他の人への財産にもなります。

    現在私が気になっているのは、前回のスレッドも含め、このスレッドが公開デバッグのようになってしまっていることです。多少であれば良いのですが、あまり多くなるとチャットのような形になり、他の人から有益な情報が得られにくくなってしまいます。kazukazu2002 さんに問題切り分けの力を付けてもらいたくて、私もあえて多少は公開デバッグ的に進めてきたところもありますので、kazukazu2002 さんの質問の仕方だけに問題があるわけではありません。kazukazu2002 さんが早く問題を解決されることを願っていますし、kazukazu2002 さんも努力されていることは伝わってきます。
    質問者よし、回答者よし、閲覧者よしの三方よしとなるように、もう少し私も気を配って行きますね。

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="GridViewOuterJoinInput3.aspx.vb" Inherits="test2010webvb.GridViewOuterJoinInput3" %>
     
    <!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">
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="shop_machineID">
            <Columns>
                <asp:TemplateField HeaderText="日別時間帯別ID" 
                    SortExpression="daytimeindex">
                    <ItemTemplate>
                        <asp:Label ID="daytimeindex" runat="server" Text='<%# Bind("daytimeindex") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="店舗商品ID" 
                    SortExpression="shop_machineID">
                    <ItemTemplate>
                        <asp:Label ID="shop_machineID" runat="server" Text='<%# Bind("shop_machineID") %>' ></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                            <asp:BoundField DataField="shop_name" HeaderText="店舗名" SortExpression="shop_name" />
                <asp:BoundField DataField="machine_name" HeaderText="商品名" SortExpression="machine_name" />
                <asp:TemplateField HeaderText="使用者数" SortExpression="men">
           <%--         <EditItemTemplate>
                        <asp:Label ID="Label1" runat="server" Text='<%# Eval("使用者数") %>'></asp:Label>
                    </EditItemTemplate>--%>
                    <ItemTemplate>
                        <asp:TextBox ID="men" runat="server" Text='<%# Bind("men") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="inputday" HeaderText="日付" 
                    SortExpression="inputday" />
                <asp:BoundField DataField="timeID" HeaderText="時間帯" ReadOnly="True" 
                    SortExpression="timeID" />
            </Columns>
        </asp:GridView>
     
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="bttn_検索" runat="server" onclick="bttn_検索_Click" Text="検索" />
        <asp:Button ID="bttn_更新" runat="server" onclick="bttn_更新_Click" Text="更新" />
     
        </form>
    </body>
    </html>
    
    Imports System.Transactions
    Imports System.Data.SqlClient
    Imports test2010webvb.DataSet2TableAdapters
     
    Public Class GridViewOuterJoinInput3
        Inherits System.Web.UI.Page
     
        Protected Sub Page_Load(ByVal sender As ObjectByVal e As EventArgsHandles Me.Load
     
        End Sub
     
        Protected Sub bttn_検索_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable1TableAdapter()
            Dim table = New DataSet2.DataTable1DataTable()
     
            tadapter.Fill(table, Integer.Parse(TextBox1.Text))
     
            GridView1.DataSource = table
            GridView1.DataBind()
     
        End Sub
     
        Protected Sub bttn_更新_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable1TableAdapter()
     
            Using tranScope = New TransactionScope()
                Using connection = New SqlConnection()
                    connection.ConnectionString = tadapter.Connection.ConnectionString
                    connection.Open()
     
                    Dim insertCommand = New SqlCommand("insert into tbl1 (shop_machineID, men) values (@shop_machineID, @men)", connection)
                    insertCommand.Parameters.Add("@shop_machineID", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
     
                    Dim updateCommand = New SqlCommand("update tbl1 set men = @men where (daytimeindex = @daytimeindex)", connection)
                    updateCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    updateCommand.Parameters.Add("@daytimeindex", System.Data.SqlDbType.Int)
     
                    For Each gr As GridViewRow In GridView1.Rows
                        Dim men As Integer = Integer.Parse(DirectCast(gr.FindControl("men"), TextBox).Text)
                        Dim shop_machineID As Integer = Integer.Parse(DirectCast(gr.FindControl("shop_machineID"), Label).Text)
                        Dim daytimeindex As Integer = Integer.Parse(DirectCast(gr.FindControl("daytimeindex"), Label).Text)
     
                        If daytimeindex = 0 Then
                            insertCommand.Parameters("@shop_machineID").Value = shop_machineID
                            insertCommand.Parameters("@men").Value = men
                            insertCommand.ExecuteNonQuery()
                        Else
                            updateCommand.Parameters("@men").Value = men
                            updateCommand.Parameters("@daytimeindex").Value = daytimeindex
                            updateCommand.ExecuteNonQuery()
     
                        End If
                    Next
                End Using
     
                tranScope.Complete()
     
            End Using
        End Sub
     
    End Class

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kazukazu2002 2012年4月3日 6:59
    2012年4月3日 5:47
    モデレータ
  • trapemiya様

    御呈示いただいたコードで動かすことができました。テーブルへの新規レコード追加および更新もできました。

    何がおかしかったのか全く分からない状態です。

    私がやったことと言えば、ソリューションエクスプローラーから新しい項目を追加から、現在のMasterPageを使わず、単独でDefault.aspxを作成、

    CodeBehind="GridViewOuterJoinInput3.aspx.vb"

    の部分が、CodeFile="Default.aspx.vb" CodeFileとCodeBehindのところが違うのは調べます。

    Inherits="test2010webvb.GridViewOuterJoinInput3"

    の部分が、Inherits="Default2" ともに名称が変わっただけなので関係なし。

    vbコードのほうも、TableAdapter名が違うだけです。

    全体的なコードはまだ見返していませんが、原因は必ず見つけます。

    現状では、私が行っていたのは、現在のMasterPageを使用し、ContentPlaceHolder内で行っていたことぐらいです。

    最終報告をさせていただきますので、今しばらくお待ちください。

    2012年4月3日 6:24
  • trapemiya様

    同じコードで動作確認をしたところ、やはり、MasterPageを使用した方ではテーブルへの登録はできませんでした。MasterPageに問題があるのでしょうか?

    コード自体は、確実な動作がありましたので、このフォーラムは閉じるべきでしょうか?上記は別問題になりますか?

    ※GridViewをform要素で括っていないのが問題でしょうか?
    2012年4月3日 6:48
  • 「MasterPageを使った場合のGridViewのRowsが取得できない」というようなタイトルで別スレッドにした方が良いでしょう。そして、そこで再現する最低限のコードを掲載して下さい。
    大事なことは、問題が再現するコードを掲載することです。問題が再現しなければ、原因を推測、調査することができません。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    2012年4月3日 6:57
    モデレータ
  • では一度閉じさせていただきます。

    今回の質問(絞り込んで頂きましたことにより明確になりました。)

    -GridViewにおいて、空テーブルへのInsertおよびUpdateの一括編集をする方法-

    解答

    DataSet(TableAdapter)を使用し、For Each文により振り分け、空テーブルに登録する

    trapemiya様、SurferOnWww様、

    超初心者である私の質問を丁寧に、かつ、やさしくご指導をしていただきました事を心より感謝申し上げます。

    いまだ、初心者ゆえの勘違いや知識不足はございますが、どうぞよろしくお願い申し上げます。

    ありがとうございました。

    2012年4月3日 7:08
  • trapemiya様

    御無沙汰しております。

    お教えいただいたコードについてお聞きしたいのですが、実際の動作として一度登録したものを編集できるという機能ですが、例えば、昨日の日付で入力して登録したデータがあるとします。その後、本日また、本日の日付で入力するデータがあって登録するとした時、昨日の日付で登録したデータを編集するという形になるような気がするのですが、新規で累積されるデータではなかったのでしょうか?

    つまり、昨日のデータが上書きされるということになりませんでしょうか?
    2012年4月15日 2:36
  • > 新規で累積されるデータではなかったのでしょうか?

    それがやりたいことなら、このページに実装する機能を、E テーブル(でしたよ
    ね?)に複数行を一度に挿入するだけに絞って、根本的にやり方を見直してはい
    かがですか。

    2012年4月15日 7:37
  • 私も今調べていて(コードをじっくり見て)、思っていたところです。

    実際にテーブルは一度出来上がるので、もし編集作業が必要なら、そのテーブルを使用してまた、別ページにでも作れば問題ないのではないかと思っていました。

    コード上で言うなら、daytimeindexが0ならInsert、そうでなければupdateなのを、どちらでもInsertで、累積になるんですよね。

    ただこれがやりたい事ではあるのですが、実装するにあたって問題がないかもう一度考えようと思います。

    2012年4月15日 7:45
  • > コード上で言うなら、daytimeindexが0ならInsert、そうでなけ
    > ればupdateなのを、どちらでもInsertで、累積になるんですよね。

    違うと思います。根本から考え直さないとダメでしょう。


    • 編集済み SurferOnWww 2012年4月15日 9:34 誤記訂正
    2012年4月15日 9:31
  • SurferOnWww様 いつもご指導頂きありがとうございます。

    >違うと思います。根本から考え直さないとダメでしょう。

    どう考え直せばよろしいのでしょうか?

    参考になるようなものがあればお教え願えませんでしょうか?

    2012年4月15日 10:39
  • >つまり、昨日のデータが上書きされるということになりませんでしょうか?

    そうなります。なぜなら日付、時間帯は既に登録されていることが前提になっているからです。この画面では人数のみ登録しています。
    店舗テーブルの1レコードについて、複数の日付時間帯別テーブルのレコードが発生するわけですよね。それは日付毎に発生するのでしょうか?
    仮にそうだとすれば、今は店舗テーブル1レコード : 日付時間帯別テーブル1レコードの関係ですから、それが以下のようになればよいわけです。

    店舗テーブル1レコード : 日付時間帯別テーブル複数レコード
    ID 1  ------ +--------ID 1    2012-04-01
                      |
                     +--------ID 2     2012-04-02
                      |
                     +--------ID 3     2012-04-03

    ですから、最初に検索する時に日付も検索条件に入れ、つまり、店舗+日付で検索し、日付と人数を入力するようにすれば良いはずです。
    おそらく検索するところに工夫がいるはずです。あとで時間が取れれば私の方でも試してみたいと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月16日 6:58
    モデレータ
  • trapemiya様 御返答ありがとうございます。

    >店舗テーブルの1レコードについて、複数の日付時間帯別テーブルのレコードが発生するわけですよね。それは日付毎に発生するのでしょうか?

    その通りです。日別時間帯別テーブル(E)の日別時間帯別IDはIDENTITYで一意、店舗商品IDは日付(毎日)と時間帯(3回)で重複することになります。(使用者数はそのレコードごとに)

    私も解らないなりに、TableAdapterでGridViewが作成(検索ボタン)直後にイベントでmachineIDに対して、dateがInsertされてから表示できないか調べていました。

    正直Update処理自体をなくせばいいのかと思っていました。違うのですね。



    ※またお忙しい中御返答をいただいた事に深く感謝申し上げます。
    2012年4月16日 7:15
  • とりあえず、日付のみで複数発生することにしてテストコードを書いてみました。

    select tbl_shop_machine.shop_machineID,
    	ISNULL(tbl1.daytimeindex, 0) as daytimeindex,
    	tbl_shop.shop_name,
    	tbl_machine.machine_name,
    	ISNULL(tbl1.men, 0) as men,
    	@inputday as inputday, 
    	ISNULL(tbl1.timeID, '') as timeID
    from tbl_shop_machine
    left outer join tbl1
         on tbl1.shop_machineID = tbl_shop_machine.shop_machineID and
            tbl1.inputday = @inputday
    inner join tbl_shop
         on tbl_shop.shopID = tbl_shop_machine.shopID
    inner join tbl_machine
         on tbl_machine.machineID = tbl_shop_machine.machineID
    where tbl_shop_machine.shopID = @shopID
    <%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/MasterPage.master" CodeBehind="GridViewOuterJoinInput5.aspx.vb" Inherits="test2010webvb.GridViewOuterJoinInput5" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
        <div id="maincontents">
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="shop_machineID">
            <Columns>
                <asp:TemplateField HeaderText="日別時間帯別ID" 
                    SortExpression="daytimeindex">
                    <ItemTemplate>
                        <asp:Label ID="daytimeindex" runat="server" Text='<%# Bind("daytimeindex") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="店舗商品ID" 
                    SortExpression="shop_machineID">
                    <ItemTemplate>
                        <asp:Label ID="shop_machineID" runat="server" Text='<%# Bind("shop_machineID") %>' ></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                            <asp:BoundField DataField="shop_name" HeaderText="店舗名" SortExpression="shop_name" />
                <asp:BoundField DataField="machine_name" HeaderText="商品名" SortExpression="machine_name" />
                <asp:TemplateField HeaderText="使用者数" SortExpression="men">
           <%--         <EditItemTemplate>
                        <asp:Label ID="Label1" runat="server" Text='<%# Eval("使用者数") %>'></asp:Label>
                    </EditItemTemplate>--%>
                    <ItemTemplate>
                        <asp:TextBox ID="men" runat="server" Text='<%# Bind("men") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
    <%--            <asp:BoundField DataField="inputday" HeaderText="日付" 
                    SortExpression="inputday" />--%>
                <asp:TemplateField HeaderText="日付" SortExpression="inputday">
                    <ItemTemplate>
                        <asp:TextBox ID="inputday" runat="server" Text='<%# Bind("inputday") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="timeID" HeaderText="時間帯" ReadOnly="True" 
                    SortExpression="timeID" />
            </Columns>
        </asp:GridView>
     
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
        <asp:Button ID="bttn_検索" runat="server" onclick="bttn_検索_Click" Text="検索" />
        <asp:Button ID="bttn_更新" runat="server" onclick="bttn_更新_Click" Text="更新" />
        </div>
    </asp:Content>

    Imports System.Transactions
    Imports System.Data.SqlClient
    Imports test2010webvb.DataSet2TableAdapters
     
    Public Class GridViewOuterJoinInput5
        Inherits System.Web.UI.Page
     
        Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgsHandles Me.Load
     
        End Sub
     
        Protected Sub bttn_検索_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable2TableAdapter()
            Dim table = New DataSet2.DataTable2DataTable()
     
            tadapter.Fill(table, DateTime.Parse(TextBox2.Text), Integer.Parse(TextBox1.Text))
     
            GridView1.DataSource = table
            GridView1.DataBind()
     
        End Sub
     
        Protected Sub bttn_更新_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable1TableAdapter()
     
            Using tranScope = New TransactionScope()
                Using connection = New SqlConnection()
                    connection.ConnectionString = tadapter.Connection.ConnectionString
                    connection.Open()
     
                    Dim insertCommand = New SqlCommand("insert into tbl1 (shop_machineID, men, inputday) values (@shop_machineID, @men, @inputday)", connection)
                    insertCommand.Parameters.Add("@shop_machineID", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@inputday", System.Data.SqlDbType.Date)
     
                    Dim updateCommand = New SqlCommand("update tbl1 set men = @men, inputday = @inputday where (daytimeindex = @daytimeindex)", connection)
                    updateCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    updateCommand.Parameters.Add("@inputday", System.Data.SqlDbType.Date)
                    updateCommand.Parameters.Add("@daytimeindex", System.Data.SqlDbType.Int)
     
                    For Each gr As GridViewRow In GridView1.Rows
                        Dim men As Integer = Integer.Parse(DirectCast(gr.FindControl("men"), TextBox).Text)
                        Dim inputday As DateTime = DateTime.Parse(DirectCast(gr.FindControl("inputday"), TextBox).Text)
                        Dim shop_machineID As Integer = Integer.Parse(DirectCast(gr.FindControl("shop_machineID"), Label).Text)
                        Dim daytimeindex As Integer = Integer.Parse(DirectCast(gr.FindControl("daytimeindex"), Label).Text)
     
                        If daytimeindex = 0 Then
                            insertCommand.Parameters("@shop_machineID").Value = shop_machineID
                            insertCommand.Parameters("@men").Value = men
                            insertCommand.Parameters("@inputday").Value = inputday
                            insertCommand.ExecuteNonQuery()
                        Else
                            updateCommand.Parameters("@men").Value = men
                            updateCommand.Parameters("@inputday").Value = inputday
                            updateCommand.Parameters("@daytimeindex").Value = daytimeindex
                            updateCommand.ExecuteNonQuery()
     
                        End If
                    Next
                End Using
     
                tranScope.Complete()
     
            End Using
        End Sub
    End Class

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月16日 7:56
    モデレータ
  • SQLは以下の方が良いかもしれません。

    select tbl_shop_machine.shop_machineID,
    	ISNULL(tbl1.daytimeindex, 0) as daytimeindex,
    	tbl_shop.shop_name,
    	tbl_machine.machine_name,
    	ISNULL(tbl1.men, 0) as men,
    	@inputday as inputday, 
    	ISNULL(tbl1.timeID, '') as timeID
    from tbl_shop_machine
    left outer join tbl1
         on tbl1.shop_machineID = tbl_shop_machine.shop_machineID and
            tbl1.inputday = @inputday and
            tbl_shop_machine.shopID = @shopID
    inner join tbl_shop
         on tbl_shop.shopID = tbl_shop_machine.shopID
    inner join tbl_machine
         on tbl_machine.machineID = tbl_shop_machine.machineID
    #(追記)いや、これだとShopIDで絞り込まれなくなっちゃいます。上のSQL文は誤りです。すみません。

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    2012年4月16日 8:01
    モデレータ
  • trapemiya様 ありがとうございます。

    上記コードにおいて、shopID(TextBox1)、inputday(TextBox2)を1、2012/4/15、で検索、ShopIDはtrapemiya様の変更後のSQLにおいて検索対象にないので全件表示され、inputdayは全て2012/4/15が入っている状態になりました。この状態で更新ボタン後、 もう一度、shopID(TextBox1)、inputday(TextBox2)を1、2012/4/15、で検索すると

    tadapter.Fill(table, DateTime.Parse(TextBox2.Text), Integer.Parse(TextBox1.Text))

    において

    System.Data.ConstraintException はユーザー コードによってハンドルされませんでした。
      Message=制約を有効にできませんでした。行に入力できるのは、Null 以外の値、一意な値、あるいは外部キーですが、この制約の違反が 1 つ以上の行で発生しています。

    というエラーが発生します。この原因はなんでしょう?

    trapemiya様が

    >とりあえず、日付のみで複数発生することにして

    とあったので日付はレコードに一括登録されました。店舗商品IDも重複できています。

    FillにおいてのParse文なのですが、DropDownListの場合は、

    Integer.Parse(DropDownList.SelectedValue)

    で問題ないでしょうか?
    また、SQLの@文のところとか、更新部分でなぜもう一度tadapterがあるのか、等、勉強確認しておきます。
    2012年4月16日 11:52
  • >ShopIDはtrapemiya様の変更後のSQLにおいて検索対象にないので全件表示され

    すみません。最後に掲載したSQL文が間違ってました。その一つ前に載せたSQL文にして下さい。

    >というエラーが発生します。この原因はなんでしょう?

    データベースから検索した結果をデータテーブルに入れる時に発生しているものと思われます。例えば主キーに設定してある列にnullを入れようとしていたり、一意でない値を入れようとした場合に発生します。テーブルアダプターにおけるそのデータテーブルの主キーになっている列に着目して下さい。この列に実際にどのような列が格納されようとしているのかは、テーブルアダプターを右クリックして「データのプレビュー」で確認して下さい。もしくは、テーブルアダプターを右クリックして構成よりSQL文を表示し、それをSQL Server Management Studioで「新しいクエリ」でクエリ作成の画面に張り付け、実行して下さい。ここでいろいろ試し、自分の思い通りの値が得られたら、そのSQLをテーブルアダプターで使うことになります。

    >とあったので日付はレコードに一括登録されました。店舗商品IDも重複できています。

    それで良いです。一つの店舗商品IDに、日付毎の複数のレコードがtbl1にできます。ただ、ここは私が勝手に仕様を想像しましたので、そうでなければ仕様を訂正する必要があります。

    >Integer.Parse(DropDownList.SelectedValue)

    >で問題ないでしょうか?

    SelectedValueが必ずInteger型にキャストできるのであれば問題ありません。

    >また、SQLの@文のところとか、更新部分でなぜもう一度tadapterがあるのか、等、勉強確認しておきます。

    @のところは単純にパラメータ値に置き換えらえるだけです。更新部分のtadapterは単に接続文字列(ConnectionString)を取り出したいためだけに使っています。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月17日 1:05
    モデレータ
  • SQL文の SELECT @inputday AS inputday,

    FROM句のtbl1.inputday = @inputday はWEBで調べてもなかなか見つからないのですが(探し方が悪いのでしょうか) DirectCastとかAddで使用していた引数の事なんでしょうか? SQL文中に使用できるんですね。

    更新部分でのtadapterは、検索時にFillで生成され保持したtableを呼び出す為?でしょうか?

    現状では、同じ日付のものは生成されない状態ですよね、日に3回時間別というものがあるので、FillにtimeID部分の追加を(inputdayのように)するとできるのかなと思いましたが、どうでしょうか?

    また、更新の部分ですが、一度登録したinputday、shopIDで、検索する(daytimeindexは0でないもの)と前レスのエラーになるのは、daytimeindexがIDENTITY設定されているから、編集(For Each文とupdateコマンド)もできないからではないでしょうか?

    追記
    ※すみません、tadapterの件、了解しました。同時でレスしてしまった為、変な形になりました。

    TableAdapterのデータのプレビューでは登録済のshopID 1、 inputday 2012/4/15、で結果表示はされるのですが、(daytimeindexも0でない)、(←できてるということですよね)

    (新規時のdaytimeindex 0も表示されます)

    デバック時になぜ前レスのエラーが出るのでしょう?


    2012年4月17日 1:11
  • >FROM句のtbl1.inputday = @inputday はWEBで調べてもなかなか見つからないのですが(探し方が悪いのでしょうか)

    「SQL 名前付きパラメータ」で検索してみて下さい。SQL文を一つの関数として考えればわかりやすいかもしれません。関数(SQL)に与えられたパラメータが、関数(SQL)内で実行されるわけです。
    ちなみに余談ですが、名前付きパラメータがあれば、無名パラメータと言って名前のないパラメータも存在します。ODBCで操作する場合は名前付きパラメータが使えませんから、無名パラメータで操作することになります。例えばAccessのmdbなどを操作する場合です。無名パラメータは名前が無いので、指定された順序でパラメータを適用していきます。
    select a from table where name = ? and age = ? というようになります。無名パラメータは全て「?」を使います。無名パラメータはプレイスフォルダとも言われたりします。
    名前付きパラメータは名前でどのパラメータか判断できますから、その値を指定する順序はどうでも良いです。

    >現状では、同じ日付のものは生成されない状態ですよね、日に3回時間別というものがあるので、FillにtimeID部分の追加を(inputdayのように)するとできるのかなと思いましたが、どうでしょうか?

    素晴らしい! その通りです。

    >更新ボタンを押すとエラーになるのは、daytimeindexがIDENTITY設定されているから、編集もできないからではないでしょうか?

    daytimeindexにIDENTITYが設定されているのはデータベース上のtbl1です。更新ボタンを押した際に正しくSQL文が発行されれば、問題ありません。
    データテーブル <--->  データベース
    になっているわけですが、検索ボタンを押した際にきちんと表示されるのであればデータテーブルにはちゃんと値が入っていますから問題ありません。更新ボタンを押した際にエラーになるのであれば、データベースへの登録・更新の際にエラーになっているわけで、正しいSQL文が発行されていない可能性があります。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    2012年4月17日 2:01
    モデレータ
  • SQLの発行に問題があるということで、

    一つ問題がありました。

    shopID、inputdayを入力し、検索ボタン後、更新ボタンを押した後、tbl1のレコードを確認したところ、登録されたレコード(daytimeindexは違う)が2重で登録されていました。←重複しているレコードを削除後、登録済み検索(更新)が可能になりました。

    エラーの原因ではないでしょうか?

    なぜ一回の操作で、同じもの(同じinputday、同じmen)が2つレコード追加されているのでしょうか?

    daytimeindex  shop_machineID  men  inputday

    1            15          5    2012/4/18

    2            20         15    2012/4/18

    3            15          5    2012/4/18

    4            20         15    2012/4/18

    という感じです。(言葉足らずかもしれませんので)(太字の分のレコードを削除した場合、登録済みデータが検索できました)














    2012年4月17日 2:46
  • なるほど。的確な情報をいただいたおかげで謎が解けました。私のコードが簡易であったため、二度続けて更新ボタンを押し、データが二重に登録されてしまったようです。
    更新ボタンを押した後は検索を実行し、最新のdaytimeindexを読み込む必要があります。よって、以下のようにコードを修正すると何度続けて更新ボタンを押しても大丈夫なはずです。(最初はdaytimeindexが0ですからinsert文が発行されてデータベースに新規登録され、その後、検索されて、データベースで採番されたdaytimeindexが読みこまれ、その後、更新ボタンを押すとdaytimeindexが0以外ですから、データベースへ今度はupdate文が実行され、更新になります。これまではいつまでも経ってもdaytimeindexが0なので二重に登録されてしまったわけです。)

    Imports System.Transactions
    Imports System.Data.SqlClient
    Imports test2010webvb.DataSet2TableAdapters
     
    Public Class GridViewOuterJoinInput5
        Inherits System.Web.UI.Page
     
        Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgsHandles Me.Load
     
        End Sub
     
        Protected Sub bttn_検索_Click(ByVal sender As ObjectByVal e As EventArgs)
            検索()
        End Sub
     
        Private Sub 検索()
            Dim tadapter = New DataTable2TableAdapter()
            Dim table = New DataSet2.DataTable2DataTable()
     
            tadapter.Fill(table, DateTime.Parse(TextBox2.Text), Integer.Parse(TextBox1.Text))
     
            GridView1.DataSource = table
            GridView1.DataBind()
        End Sub
     
        Protected Sub bttn_更新_Click(ByVal sender As ObjectByVal e As EventArgs)
            Dim tadapter = New DataTable1TableAdapter()
     
            Using tranScope = New TransactionScope()
                Using connection = New SqlConnection()
                    connection.ConnectionString = tadapter.Connection.ConnectionString
                    connection.Open()
     
                    Dim insertCommand = New SqlCommand("insert into tbl1 (shop_machineID, men, inputday) values (@shop_machineID, @men, @inputday)", connection)
                    insertCommand.Parameters.Add("@shop_machineID", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    insertCommand.Parameters.Add("@inputday", System.Data.SqlDbType.Date)
     
                    Dim updateCommand = New SqlCommand("update tbl1 set men = @men, inputday = @inputday where (daytimeindex = @daytimeindex)", connection)
                    updateCommand.Parameters.Add("@men", System.Data.SqlDbType.Int)
                    updateCommand.Parameters.Add("@inputday", System.Data.SqlDbType.Date)
                    updateCommand.Parameters.Add("@daytimeindex", System.Data.SqlDbType.Int)
     
                    For Each gr As GridViewRow In GridView1.Rows
                        Dim men As Integer = Integer.Parse(DirectCast(gr.FindControl("men"), TextBox).Text)
                        Dim inputday As DateTime = DateTime.Parse(DirectCast(gr.FindControl("inputday"), TextBox).Text)
                        Dim shop_machineID As Integer = Integer.Parse(DirectCast(gr.FindControl("shop_machineID"), Label).Text)
                        Dim daytimeindex As Integer = Integer.Parse(DirectCast(gr.FindControl("daytimeindex"), Label).Text)
     
                        If daytimeindex = 0 Then
                            insertCommand.Parameters("@shop_machineID").Value = shop_machineID
                            insertCommand.Parameters("@men").Value = men
                            insertCommand.Parameters("@inputday").Value = inputday
                            insertCommand.ExecuteNonQuery()
                        Else
                            updateCommand.Parameters("@men").Value = men
                            updateCommand.Parameters("@inputday").Value = inputday
                            updateCommand.Parameters("@daytimeindex").Value = daytimeindex
                            updateCommand.ExecuteNonQuery()
     
                        End If
                    Next
                End Using
     
                tranScope.Complete()
     
            End Using
     
            検索()
        End Sub
    End Class

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kazukazu2002 2012年4月18日 6:38
    2012年4月17日 4:53
    モデレータ
  • trapemiya様 ありがとうございました。上記編集の際の問題は解決いたしました。 

    追加された”検索()”の意図はまだ理解できていませんが、

    同時進行で、TableAdapterに必要なshopIDのような分岐条件をもう一つ入れる(商品の種類(id)を分別する)

    SQL文はこれで問題ないでしょうか?

    WHERE (tbl_shop_machine.shopID = @shopID) AND (tbl_shop_machine.id = @id)

    SQLの問題か、VBのInteger.Parse(DropDownList_id.Text)の部分が問題なのか解りません。

    ※時間帯分岐は大丈夫でした。(TextBoxでやっただけなのでDropDownListの場合どうなるかは解りませんが)

    もう少し検証していこうと思います。

    ※追記

    種類(id)での絞り込みはできなかったのでもう一度考えます。

    時間帯分岐(というか行に対して一括で値を入れる)はDropDownListでも問題なく、一連の処理ができました。

    もうひとつ、Parse処理(天気を入れたい)をしたくて、時間帯(timeID)と同じようにSQLとVB、aspxを書いたのですが、TableAdapterのデータプレビューでは、生成することができました。

    TableAdapterのFillのParse処理は、tableを生成して、その指定する行に値を入れるのですよね?

    しかし、デバック時に、天気(4レコード{1.2.3.4})で’1’であればtableが生成され、それ以外を選択するとtableが生成されないのです。














    2012年4月17日 9:22
  • >追加された”検索()”の意図はまだ理解できていませんが、

    先にも書きましたが、daytimeindex=0の場合、データベースへ新規登録に行きます。新規登録された結果、データベース上でdaytimeindexは採番されます。この採番された値を検索()して取得しなければ、クライアント側ではいつまで経ってもdaytimeindex=0のままですから、更新ボタンを押す度にデータベースに新規登録されてしまいます。

    >SQL文はこれで問題ないでしょうか?(TableAdapterでtable作成されたときにうまくいきませんでしたが)

    SQLは問題ありません。tbl_shop_machineテーブルからshopIDとidで絞り込み、その絞り込んだレコードに対するtbl1のレコードをouter joinすることになります。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月18日 1:49
    モデレータ
  • trapemiya様 ありがとうございます。

    検索()の件ありがとうございます。理解するのは難しいですね。(特に日本語解釈)、解りやすくご指導頂きありがとうございます。

    id絞り込みの件、うまくいきました。(なぜこれで悩んでいたのか不思議なくらいです。)

    >しかし、デバック時に、天気(4レコード{1.2.3.4})で’1’であればtableが生成され、それ以外を選択するとtableが生成されないのです。

    SQL、aspx、VBも(時間帯)と同じ設定なのですが、なぜかできません。なにを見ればよろしいでしょうか?

    ※追記

    ブレークポイントで、tadapter.Fill~の値を確認したのですが、入力した(選択した)数値は入っていました。、生成されたtableは、天気1の場合の結果は数値(名前)などきちんと入っています(つまりテーブル表示される)が、天気1以外で会った場合、生成自体されていないようです。つまりSQLに問題があるのでしょうか?



    2012年4月18日 2:47
  • >SQL、aspx、VBも(時間帯)と同じ設定なのですが、なぜかできません。なにを見ればよろしいでしょうか?

    TableAdapterのデータプレビューではうまく見れているということですので、SQL文は問題ありません。となると、そのSQL文のパラメータに何らかの原因でうまく値が渡せていないのだと思います。デバッグ実行して、天気で1以外を選択した時にどのような値がパラメータにセットされているのかをチェックする必要があります。
    デバッグでは問題をどんどん切り分けていき、最終的にどこに間違いがあるのかを突き止める手順で行って下さい。バグの箇所を突き止めるには、大きな単位で絞り込んでいき、だんだん小さな単位に絞り込んで見つけるのが基本です。どこまで正しく動いているのかを順を追って確かめていきましょう。正しく動いていないところが見つかれば、その処理の前のどこかにバグがあるということです。

    #このスレッドも一つの問題が解決すれば次の問題へと移り、どんどん長くなっています。シームレス的なところもあって気持ちはわかりますが、解決の方向性は出ており、現在はバグを取るためのやり取になっている感が強くなっています。この質問が悪いというわけではありませんが、このスレッドのタイトルとは直接関係なくなってきていますので、まだ解決しないようであれば新たにスレッドを立てられた方が良いでしょう。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 山本春海 2012年4月19日 2:25
    2012年4月18日 5:03
    モデレータ
  • trapemiya様 御返答ありがとうございます。

    そうですね。解りました。デバックから一つ一つもう一度きちんと見てみます。

    本当にお世話になりっぱなしで申し訳がありません。もっと勉強しますので、また、調べた上でわからない点がありましたら、どうぞよろしくお願い申し上げます。

    2012年4月18日 6:38
  • ひとつだけこちらのレスで質問します。

    Eテーブルへの登録の際、shop_name、machine_nameが空のままだったのですが、

    テーブルへの登録はどのようにするのでしょうか?

    文字列を文字列に変換? 基礎的なことですよね、数値の型変換はなんとかわかるのですが、GridViewRowの場合はどのようにするのでしょう?

    For Eachの部分は

    Dim machine_name As TextBox = DirectCast(gr.FindControl("machine_name"), TextBox)

    で問題ないでしょうか?(これはコントロールを取得しただけ?)

    2012年4月19日 2:15
  • BoundFieldではなく、TemplateFieldで定義し、IDをきちんと設定して下さい。そうすれば人数と同様の手順で取得できるはずです。うまく動かなければ、動いている部分と比較し、真似をしていろいろと試してみて下さい。
    ただ、テーブル設計的にはEテーブル(tbl1)にshop_name、machine_nameを持たせる必要はありません。tbl1のshop_machineIDより、tbl_shop_machineが読め、そのshopIDやmachineIDよりshop_name, machine_nameを読むことができます。

    select t1.daytimeindex, s.shop_name, m.machine_name
    from tbl1 as t1
    inner join tbl_shop_machine as sm on sm.shop_machineID = t1.shop_machineID
    inner join tbl_shop as  s on s.shopID = sm.shopID
    inner join tbl_machine as m on m.machineID = sm.machineID

    #山本さまより回答マークが付いています。回答マークが付いたスレッドで新たにやり取りを行うのは好ましいことではありませんので、新しくスレッドを立てるようにして下さい。スレッドのタイトルと違う内容で質問が繰り返されては、いつまで経ってもスレッドが閉じなくなってしまいます。申し訳ありませんが、このスレッドでの回答に関する書き込みはこれ以上控えさせていただきます。これ以降の質問は別スレッドでお願いいたします。厳しいことを言うようで心苦しいのですが、よろしくお願いいたします。

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2012年4月19日 4:44
    モデレータ