必须在使用DataView之前设置DataTable。我以错误的方式绑定我的数据吗?

时间:2016-04-29 02:42:23

标签: asp.net vb.net sorting gridview dataview

自从我开始这个项目以来已经过了一个星期,但我对于要解决的问题完全无能为力。这里是我编码的一部分。

Protected Sub bpn_Click(sender As Object, e As EventArgs)
    Try
      Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("SQLServer2005DBConnectionString").ToString())
        connection.Open()
        Dim sql As String = ("select * from LOT_ WHERE PRODUCTNAME ='" & txtbpn.Text & "'")
        Dim cmd As SqlCommand = New SqlCommand(sql, connection)
        Using reader As SqlDataReader = cmd.ExecuteReader
            If reader.HasRows Then
                lblerror.Visible = False
                connection.Dispose()
                connection.Close()
                Me.BindBpn()

                txtbpn.Text = String.Empty
                TextBox2.Text = String.Empty
                TextBox3.Text = String.Empty
                TextBox4.Text = String.Empty
                TextBox5.Text = String.Empty
            Else
                connection.Dispose()
                connection.Close()

                lblerror.Text = "bpn not found"
                lblerror.Visible = True
                txtbpn.Text = String.Empty
                TextBox2.Text = String.Empty
                TextBox3.Text = String.Empty
                TextBox4.Text = String.Empty
                TextBox5.Text = String.Empty
            End If
        End Using
    Catch ex As Exception
        Response.Write(ex.Message)
        Response.AppendHeader("Refresh", "1;url=Summary.aspx")
    End Try
End Sub

1.绑定子

    Private Sub BindBpn()

  Using con As New SqlConnection(ConfigurationManager.ConnectionStrings("SQLServer2005DBConnectionString").ToString())
        Using cmd As New SqlCommand("SELECT * FROM LOT_ WHERE PRODUCTNAME='" & txtbpn.Text & "'order by checkin asc")
            Using sda As New SqlDataAdapter()
                con.Open()
                cmd.Connection = con
                sda.SelectCommand = cmd
                Dim dt As New DataTable()
                sda.Fill(dt)
                Dim dv As New DataView(dt)

                GridView1.DataSource = dv
                GridView1.DataBind()
                ' Me.BindGridView()
                con.Close()

            End Using
        End Using
    End Using
    If GridView1.Visible = False Then
        GridView1.Visible = True
    End If
    If Button1.Visible = False Then
        Button1.Visible = True
    End If
End Sub

2.当我尝试对数据进行排序时发生错误。

Protected Sub SortRecords(sender As Object, e As GridViewSortEventArgs)

    Dim SortDir As String = String.Empty
    Dim sortExpression As String = e.SortExpression


    Dim dv As New DataView(GridView1.DataSource) 
    If dv IsNot Nothing Then
        If direction = SortDirection.Ascending Then
            direction = SortDirection.Descending

            SortDir = "Desc"
            ViewState("SortExpression") = Convert.ToString(e.SortExpression & " " & SortDir)
        Else
            direction = SortDirection.Ascending

            SortDir = "Asc"
            ViewState("SortExpression") = Convert.ToString(e.SortExpression & " " & SortDir)

        End If


    End If

    dv.Sort = ViewState("SortExpression").ToString 
    GridView1.DataSource = dv
    GridView1.DataBind()
end sub

此代码发生错误

dv.Sort = ViewState("SortExpression").ToString 

任何帮助都会很棒。提前致谢

这是我的aspx GridView:

  <asp:GridView ID="GridView1" width="100%" runat="server" 
              AllowSorting="True" 
              OnSorting="SortRecords"  
              OnRowDataBound="GridView1_RowDataBound"   
              ItemStyle-HorizontalAlign="Center" 
              AutoGenerateColumns="False" >
    <Columns>
      <asp:TemplateField HeaderText="ID"  ItemStyle-HorizontalAlign="Center">
        <ItemTemplate>
          <%# Container.DataItemIndex + 1 %>
        </ItemTemplate>
        <ItemStyle HorizontalAlign="center" Width="5%" />
      </asp:TemplateField>

      <asp:BoundField DataField="Location" HeaderText="Location" />
      <asp:BoundField DataField="LOT_ID" HeaderText="Lot ID"  />
      <asp:BoundField DataField="PkgName" HeaderText="PIN PACKAGE NAME" />
      <asp:BoundField DataField="MBTBoardNo" HeaderText="MBTBoardNo" SortExpression="MBTBoardNo" />
      <asp:BoundField DataField="BTProgramName" HeaderText="BT Program Name"  />
      <asp:BoundField DataField="ProductRank" HeaderText="ProdRank"/>
      <asp:BoundField DataField="BASEPRODUCTNAME" HeaderText="BPN" />
      <asp:BoundField DataField="MCNo" HeaderText="MC No" />
      <asp:BoundField DataField="QTY" HeaderText="Qty" />
      <asp:BoundField DataField="CreateDate" HeaderText="Start Date" />
      <asp:BoundField DataField="CheckIn" HeaderText="CheckIn" />
      <asp:BoundField DataField="CheckOut" HeaderText="CheckOut" />  
    </Columns>
  </asp:GridView>

1 个答案:

答案 0 :(得分:0)

这可能有点矫枉过正,但我​​需要解释一些事情。

除了Sql注入攻击之外,你还有很多其他事情要先了解。

  1. 您在排序时遇到问题,因为您没有将检索到的数据缓存到任何持久性机制。排序机制中的此代码将始终评估为Nothing:

    Dim dv As New DataView(GridView1.DataSource)

  2. 除非您支持,否则GridView DataSource不会在回发中保留 使用像SqlDataSource这样的缓存数据控件来管理 缓存给你。

  3. 或者您通过以下方式之一以编程方式执行此操作:

    1. ViewState(坏主意)
    2. SessionState(不完美)
    3. 应用程序缓存(理想)
  4. 但回归基础:

    以下是帖子第一部分的经过编辑和注释的版本 我将在此之后提供清理版本:

    Protected Sub bpn_Click(sender As Object, e As EventArgs)
      ' Added for clarity
      Dim cs as String = ConfigurationManager.ConnectionStrings("SQLServer2005DBConnectionString").ToString()
      ' Try is generally not needed if you are using Using
      ' at least not here. Move it to the inner most Using block and 
      ' wrap it around the actual command execution to catch sql errors
      ' you want to personally manage.
    
      ' Try   
    
      Using connection As New SqlConnection(cs)
          connection.Open()
         ' String.Format() - learn to love this function 
         Dim sql As String = String.Format("select * from LOT WHERE PRODUCTNAME ='{0}' order by checkin asc", txtbpn.Text)
    
         Dim cmd As SqlCommand = New SqlCommand(sql, connection)
    
           ' This reader is not necessary as all you are doing 
           ' is using it to determine if there is anything to do
           ' This is a waste of time
           ' You already have one open connection and 
           ' now you are jumping to a bind operation 
           ' that opens more. 
           ' Generally speaking: 
           '   open a data connection, get the data, close the connection
           Using reader As SqlDataReader = cmd.ExecuteReader
    
             ' Do this here, not in both parts of the `If`
             lblerror.Visible = reader.HasRows
    
             ' lblerror.Text can be initialized here or in the .aspx 
             ' as you do nothing else with it but toggle its visibility
             ' Plus you can make use of a GridView's EmptyDataText property
             ' and get rid of the Label altogether.
             lblerror.Text = "bpn not found"
    
             If reader.HasRows Then
    
                 Me.BindBpn() 
    
             End If
    
             ' This code is not needed as it's handled by the outer Using
             ' connection.Dispose()
             ' connection.Close()
    
             // Since this code happens in both parts of the 
             // IF, it only needs to happen once.
             txtbpn.Text = String.Empty
             TextBox2.Text = String.Empty
             TextBox3.Text = String.Empty
             TextBox4.Text = String.Empty
             TextBox5.Text = String.Empty
    
          // Check your original code: 2 Using requires 2 End Using  
          End Using
        End Using
      ' See Try above
      Catch ex As Exception
          Response.Write(ex.Message)
    
          'Why are you trying to refresh every second?
          Response.AppendHeader("Refresh", "1;url=Summary.aspx")
      End Try
    End Sub
    

    以下是没有所有评论的修订代码

    Protected Sub bpn_Click(sender As Object, e As EventArgs)
      Dim cs as String = ConfigurationManager.ConnectionStrings("SQLServer2005DBConnectionString").ToString()
      Using connection As New SqlConnection(cs)
         connection.Open()
         Dim sql As String = String.Format("select * from LOT WHERE PRODUCTNAME ='{0}' order by checkin asc", txtbpn.Text)
    
         Dim cmd As SqlCommand = New SqlCommand(sql, connection)
    
         Using sda As New SqlDataAdapter( cmd )
            Try
              Dim dt As New DataTable()
              sda.Fill(dt)
              Dim dv as New DataView(dt)
    
              ' This will persist the retrieved record set
              ' -- Replaced C# syntax with VB 
              Cache("AStringToIdentifyThisGridviewCache") = dv
              GridView1.DataSource = Cache("AStringToIdentifyThisGridviewCache")
    
              Gridview1.EmptyDataText = "bpn not found"
              GridView1.DataBind()
              GridView1.Visible = (GridView1.Rows.Count > 0)
    
              txtbpn.Text = String.Empty
              TextBox2.Text = String.Empty
              TextBox3.Text = String.Empty
              TextBox4.Text = String.Empty
              TextBox5.Text = String.Empty
    
            Catch ex As Exception
              Gridview1.EmptyDataText = ex.Message
            End Try
    
         End Using
        End Using
    End Sub
    

    还有一件事,你的数据将从数据库中检索出来,每次点击按钮时都会覆盖Cache并重新绑定到GridView。

    通常,您希望一次检索数据,然后使用Cached数据集,直到以某种方式修改数据,这需要另一个数据库命中。

    程序化数据检索和绑定当然很有用,但我发现我很少需要使用它。您可能不满足此项目的要求,但对于GridView操作,很难超越提供的DataSource控件。

    希望这会有所帮助。 快乐的编码。

    从用于GridView排序的MSDN示例中取出的排序代码

      Protected Sub SortRecords(ByVal sender As Object, ByVal e As GridViewSortEventArgs)
    
        'Retrieve the table from the session object.
        Dim dv As DataView = TryCast(Cache("AStringToIdentifyThisGridviewCache"), DataView)
    
        If dv IsNot Nothing Then
            'Sort the data.
            dv.Sort = e.SortExpression & " " & GetSortDirection(e.SortExpression)
            GridView1.DataSource = Cache("AStringToIdentifyThisGridviewCache")
            GridView1.DataBind()
    
        End If
    
      End Sub
    
    
      Private Function GetSortDirection(ByVal column As String) As String
    
        ' By default, set the sort direction to ascending.
        Dim sortDirection = "ASC"
    
        ' Retrieve the last column that was sorted.
        Dim sortExpression = TryCast(ViewState("SortExpression"), String)
    
        If sortExpression IsNot Nothing Then
            ' Check if the same column is being sorted.
            ' Otherwise, the default value can be returned.
            If sortExpression = column Then
                Dim lastDirection = TryCast(ViewState("SortDirection"), String)
                If lastDirection IsNot Nothing _
                  AndAlso lastDirection = "ASC" Then
    
                    sortDirection = "DESC"
    
                End If
            End If
        End If
    
        ' Save new values in ViewState.
        ViewState("SortDirection") = sortDirection
        ViewState("SortExpression") = column
    
        Return sortDirection
    
      End Function