2

私が持っているトリプルネストされたリピーターロジックの問題について助けを探しています。

背景
SQL Server データベースからデータを取得して、部屋とリソースを予約するための時刻表システムを構築しています。

テーブル構造

Table 1 - tblrooms  
room_id (INT) PK  
room_name (varchar(50))  
room_resource (INT)  

Table 2 - tblperiods  
period_id (INT) PK  
period_time_start (DATETIME)  
period_time_end (DATETIME)  
period_name (nvarchar(50))  

Table 3 - tblbookings  
booking_id (INT) PK  
period_id (INT)  
room_id (INT)  
booking_status (INT)  
booking_date (DATETIME)  
booking_subject (nvarchar(50))

私が抱えている問題のほとんどは、リピーターが必要に応じてデータを引き出すことでしたが、最初の列だけが入力され、予約データを引き出して必要に応じて時刻表を作成する方法を見つけるのに本当に苦労しています。(私がすでに動作しているものの添付のスクリーンショットを参照してください)

ASPX ページ コード

<asp:Repeater ID="drPeriods" runat="server" OnItemDataBound="drPeriods_OnItemDataBound">

        <HeaderTemplate>
        <table class="table table-striped table-bordered table-condensed">
            <tr>
                <th style="width:16.66%"><asp:Label ID="lblResourceHeader" runat="server" /></th>
        </HeaderTemplate>

         <ItemTemplate>

                <th style="width:16.66%"><asp:Label ID="lblPeriod" runat="server" Text='<%# Eval("period_name") %>' /> - <asp:Label ID="lblPeriodStart" runat="server" Text='<%# Eval("period_time_start") %>' /> to <asp:Label ID="lblPeriodEnd" runat="server" Text='<%# Eval("period_time_end") %>' /></th>

         </ItemTemplate>

         <FooterTemplate>
             </tr> 

             <asp:Repeater ID="drResources" runat="server" OnItemDataBound="drResources_OnItemDataBound">

                    <ItemTemplate>

                    <tr>
                        <td height="50">
                            <asp:Label ID="lblResource" runat="server" Text='<%# Eval("room_name") %>' />
                            <br /><asp:Label ID="lblResourceDetails" runat="server" />
                        </td>
                        <asp:Label ID="lblFreeBooking" runat="server" Visible="false" />

                        <asp:Repeater ID="drBookings" runat="server" OnItemDataBound="drBookings_OnItemDataBound">

                            <ItemTemplate>

                                <td height="50">
                                    <asp:Label ID="lblCellContent" runat="server" />
                                </td>

                            </ItemTemplate>

                        </asp:Repeater>

                    </tr>

                    </ItemTemplate>

                </asp:Repeater>

            </table>

         </FooterTemplate>

     </asp:Repeater>

コードビハインド

Namespace Staff

Public Class Rb
    Inherits System.Web.UI.Page
    Private _periodId As Integer


    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If Not IsPostBack Then

            txtDate.Text = Request.QueryString("d")

            'check for weekend dates, show message if it is.
            Dim iWeekday As Integer = Weekday(Request.QueryString("d"))

            If iWeekday = 1 Or iWeekday = 7 Then

                lblMsg.Text = "<div class='alert alert-info alert-block'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;It's the weekend.</h4><p>The date you have choosen is a weekend, resources cannot be booked on weekends.</p></div>"
                lblMsg.Visible = True
                drPeriods.Visible = False

            Else

                Dim objConnection As SqlConnection
                Dim objCommand As SqlCommand
                Dim objDataReader As SqlDataReader

                objConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OPSDConnectionString").ConnectionString)

                'Get Periods
                objCommand = New SqlCommand("SELECT period_id, CONVERT(char(5), period_time_start, 108) AS period_time_start, CONVERT(char(5), period_time_end, 108) AS period_time_end, period_name FROM tblrb_periods", objConnection)

                Try
                    objConnection.Open()
                    objDataReader = objCommand.ExecuteReader()

                    If objDataReader.HasRows Then

                        drPeriods.DataSource = objDataReader
                        drPeriods.DataBind()
                        objDataReader.Close()

                    Else

                        drPeriods.Visible = False
                        lblMsg.Text = "<div class='alert alert-error alert-block'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;Error!</h4><p>Periods have not yet been setup, please set these up by selecting the periods tab above, if you cannot see this tab please ask the helpdesk administrator to set these up for you.</p></div>"
                        lblMsg.Visible = True
                        objDataReader.Close()

                    End If

                Catch ex As Exception

                    'Inform of the error
                    Elmah.ErrorSignal.FromCurrentContext().Raise(ex)

                Finally
                    objCommand.Dispose()
                    objConnection.Close()
                    objConnection.Dispose()

                End Try

            End If

        End If

    End Sub

    Protected Sub drPeriods_OnItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles drPeriods.ItemDataBound

        If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then

            _periodId = e.Item.DataItem("period_id")

        End If

        If e.Item.ItemType = ListItemType.Header Then

            Dim lblResourceHeader As Label = drPeriods.Controls(0).Controls(0).FindControl("lblResourceHeader")
            Dim layoutView As Integer = Request.QueryString("v")
            Select Case layoutView
                Case 1 ' Rooms
                    lblResourceHeader.Text = "Rooms"
                Case 2 ' Resources
                    lblResourceHeader.Text = "Resources"
                Case 3 ' Both
                    lblResourceHeader.Text = "Rooms &amp; Resources"
                Case Else
                    lblResourceHeader.Text = "Rooms &amp; Resources"
            End Select

        End If

        If e.Item.ItemType = ListItemType.Footer Then

            Dim objConnection As SqlConnection
            Dim objCommand As SqlCommand
            Dim objDataReader As SqlDataReader

            'find repeater in the footer of drPeriods (repeater)
            Dim drResources As Repeater = drPeriods.Controls(drPeriods.Controls.Count - 1).Controls(0).FindControl("drResources")
            Dim layoutView As Integer = Request.QueryString("v")

            'Get Rooms
            objConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OPSDConnectionString").ConnectionString)

            Select Case layoutView
                Case 1 ' Rooms
                    objCommand = New SqlCommand("SELECT * FROM tblrb_rooms WHERE room_resource = 1 ORDER BY room_name", objConnection)
                Case 2 ' Resources
                    objCommand = New SqlCommand("SELECT * FROM tblrb_rooms WHERE room_resource = 2 ORDER BY room_name", objConnection)
                Case 3 ' Both
                    objCommand = New SqlCommand("SELECT * FROM tblrb_rooms ORDER BY room_name", objConnection)
                Case Else
                    objCommand = New SqlCommand("SELECT * FROM tblrb_rooms ORDER BY room_name", objConnection)
            End Select

            Try
                objConnection.Open()
                objDataReader = objCommand.ExecuteReader()

                drResources.DataSource = objDataReader
                drResources.DataBind()
                objDataReader.Close()

            Catch ex As Exception

                'Inform of the error
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex)

            Finally
                objCommand.Dispose()
                objConnection.Close()
                objConnection.Dispose()

            End Try

        End If

    End Sub

    Protected Sub drResources_OnItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs)

        If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then

            Dim lblResourceDetails As Label = e.Item.FindControl("lblResourceDetails")
            If e.Item.DataItem("room_resource") <> 2 Then
                lblResourceDetails.Text = "[ <a href='#' class='withajaxpopover' title='Room Details' data-load='resourceManagerViewDetails.aspx?id=" & e.Item.DataItem("room_id") & "'>View Room Details</a> ]"
            End If

            Dim objConnection As SqlConnection
            Dim objCommand As SqlCommand
            Dim objDataReader As SqlDataReader
            Dim drBookings As Repeater = e.Item.FindControl("drBookings")
            Dim lblFreeBooking As Label = e.Item.FindControl("lblFreeBooking")

            'Get Bookings
            objConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OPSDConnectionString").ConnectionString)
            objCommand = New SqlCommand("SELECT tblrb_bookings.booking_status, tblrb_bookings.booking_subject, tblrb_bookings.booking_notes FROM tblrb_bookings WHERE (tblrb_bookings.room_id = @room_id) AND (tblrb_bookings.booking_date = @booking_date) AND (tblrb_bookings.period_id = @period_id)", objConnection)

            objCommand.Parameters.Add("@room_id", SqlDbType.Int, 10).Value = e.Item.DataItem("room_id")
            objCommand.Parameters.Add("@period_id", SqlDbType.Int, 10).Value = _periodId
            objCommand.Parameters.Add("@booking_date", SqlDbType.DateTime).Value = Request.QueryString("d")

            Try
                objConnection.Open()
                objDataReader = objCommand.ExecuteReader()

                If objDataReader.HasRows Then

                    drBookings.DataSource = objDataReader
                    drBookings.DataBind()
                    objDataReader.Close()

                Else

                    'free period
                    lblFreeBooking.Text = "<td height='50'><div class='alert alert-block alert-success'><h4 class='alert-heading'><i class='icon-ok'></i>&nbsp;Free.</h4><p><a href='#'>Click here to book this resource.</a></p></div></td>"
                    lblFreeBooking.Visible = True

                End If

            Catch ex As Exception

                'Inform of the error
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex)

            Finally
                objCommand.Dispose()
                objConnection.Close()
                objConnection.Dispose()

            End Try

        End If

    End Sub

    Protected Sub drBookings_OnItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs)

        Dim lblCellContent As Label = e.Item.FindControl("lblCellContent")

        Select Case e.Item.DataItem("booking_status")
            Case 1
                'timetabled
                lblCellContent.Text = "<div class='alert alert-block alert-error'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;Timetabled.</h4><p>" & e.Item.DataItem("booking_subject") & "</p></div>"

            Case 2
                'user booked
                lblCellContent.Text = "<div class='alert alert-block'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;Booked.</h4><p>" & e.Item.DataItem("booking_subject") & ".</p></div>"

        End Select

    End Sub


    Protected Sub btnDateSelect_Click(sender As Object, e As System.EventArgs) Handles btnDateSelect.Click

        'quick reload of page
        Response.Redirect("resourceManager.aspx?v=" & Request.QueryString("v") & "&d=" & txtDate.Text)

    End Sub

End Class End Namespace

タイムテーブルが作成されたときに、対応する列の各セルの正しい予約データが部屋と期間に含まれるように、必要なレイアウトを取得する方法を教えてください。

あなたが提供できる指針を前もって感謝します.3日間を費やして、私は新鮮な目で行うことができました:-)

よろしく、

オジー

リピーターデータの問題

4

2 に答える 2

3

まず第一に、私はあなたがコントロールをしている方法を過度に複雑にしていると思います. データベース アクセスに LINQ または EF を使用する場合は、2 つのネストされたリピーターを使用し、複雑なコード ビハインドを使用せずにこれを行うことができます。ただし、クエリを次のように単純化することから始めることができます。

SELECT *
FROM tblperiods p
    CROSS JOIN tblrooms r
    LEFT JOIN tblbookings b ON p.period_id = b.period_id AND r.room_id = b.room_id AND b.booking_date = '2012-08-01'

これにより、特定の日の単一のクエリで出力全体を生成するのに十分な情報が得られます。EF や LINQ-to-SQL を使用したくない場合でも、少しの LINQ マジックを実行して、これを部屋ごとにさらに分離することができます。これをデータバインディングに使用できます (C# を許してください。VB.NET は少し錆びている!):

DataTable dt = new DataTable();
dt.Fill(objDataReader);          // Loads all data into the DataTable
var groupedRows = dt.Rows.Cast<DataRow>().GroupBy(row => new { RoomId = (int) row["room_id"], RoomName = (string) row["room_name"] });
rpRows.DataSource = groupedRows;
rpRows.DataBind();

次に、次のようなリピーターがあります。

<table>
<thead><tr><th>Rooms &amp; Resources</th>
<asp:Repeater runat="server" id="rpHeader">
    <ItemTemplate>
        <td><%# Eval("period_name") %></td>
    </ItemTemplate>
</asp:Repeater>
</tr></thead>
<asp:Repeater runat="server" id="rpRows">
    <ItemTemplate>
        <tr>
            <th><!-- Put room header stuff here --><%# Eval("Key.RoomName") %></th>
            <asp:Repeater runat="server" DataSource="<%# Container.DataItem %>">
                <ItemTemplate>
                    <td>
                         <!-- Per-booking info -->
                         <asp:Label runat="server" Visible='<%# Eval("booking_id") == DBNull.Value %>'>Not Booked</asp:label>
                         <asp:Label runat="server" Visible='<%# Eval("booking_id") != DBNull.Value %>'>Booked!</asp:label>
                    </td>
                </ItemTemplate>
            </asp:Repeater>
        </tr>
    </ItemTemplate>
</asp:Repeater>
</table>

ヘッダー行をデータバインドするためのコードは示していませんが、これは単にselect * from tbl_periods

このコードはテストされていないことに注意してください。おそらく、データ バインディングを少し調整する必要があります。

于 2012-08-05T18:45:42.867 に答える
0

私に飛び出すのは、この行です...

Dim drResources As Repeater = drPeriods.Controls(drPeriods.Controls.Count - 1).Controls(0).FindControl("drResources") 

のようなものに置き換えてみてください

Dim drResources As Repeater = e.Item.FindControl("drResources")

(構文は少しずれているかもしれません-私のVBは不安定です:)

また、基本が機能するまで削除しtry catchます-エラーが生成されている可能性がありますが、表示されることはありません.

于 2012-08-05T18:03:44.390 に答える