通过 datagridview 搜索值

Posted

技术标签:

【中文标题】通过 datagridview 搜索值【英文标题】:Searching values via a datagridview 【发布时间】:2015-11-13 20:30:42 【问题描述】:

我尝试通过在文本框中输入文本,然后使用 SQL 查询数据库,然后在 datagridview 中显示结果来搜索数据库中的特定值。

代码如下:

  Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSearch.TextChanged
    Connection.Open()
    Dim dataTable As New DataTable
    Dim dataSet As New DataSet
    dataSet.Tables.Add(dataTable)
    Dim dataAdapter As New OleDbDataAdapter
    Dim SQLQuery As String
    SQLQuery = <sql> 
            SELECT * 
                 FROM Students
                 WHERE StudentFirstName = @StudentFirstName
                </sql> .Value

    dataAdapter = New OleDbDataAdapter(SQLQuery, Connection)
    dataAdapter.SelectCommand.Parameters.Add("@StudentFirstName", SqlDbType.Text).Value = txtStudentFirstname.Text
    dataAdapter.Fill(dataTable)
    dgrStudentDatabaseViewer.DataSource = dataTable.DefaultView
    ShowItems()
    Connection.Close()
End Sub

调用 ShowItems() 刷新 datagridview 这里是它的代码

 Private Sub ShowItems() ' the following delcleration are used for displaying the contents of the table
    Dim dataAdapter As New OleDbDataAdapter
    Dim DataTable As New DataTable
    Dim DataSet As New DataSet
    Dim SQLQuery As String = <sql>SELECT * FROM Students</sql>
    DataSet.Tables.Add(DataTable)
    dataAdapter = New OleDbDataAdapter(SQLQuery, Connection)
    dataAdapter.Fill(DataTable) ' fills the content from the database into the table in vb net
    dgrStudentDatabaseViewer.DataSource = DataTable.DefaultView
    Connection.Close()
End Sub

目前,当我尝试搜索时,什么也没有发生,datagridview 的内容保持原样。我认为这可能与我的 SQL 查询的 XML 文字有关,但无法弄清楚。

提前致谢。

【问题讨论】:

首先,每次用户键入字母时,您都会触发查询。如果我输入“h..a..s..a..n”,在我完成之前它不会找到“H”或“ha”等姓氏。因此,将第一部分移动到搜索按钮单击中。其次,第一个块中的代码正确使用了 xml 文字(.Value),第二个则没有。使用数据源不需要整个 ShowItems 方法。两个块都没有使用它们声明的数据集。 如果您要停止一遍又一遍地重新创建数据库对象,您可以使用行过滤器属性:myStudentDataView.RowFilter = String.Format("StudentName = 0", textbox1.Text) @Plutonix 首先,当您说第一部分时,您指的是哪一部分。其次,我将在哪里放置行过滤器。 第一部分 == 你的第一个代码块 第二部分 == 你的第二个代码块。您还应该打开 Option Strict。即使搜索确实有效,您也可以通过调用运行新 SQL 的 ShowItems 来撤消显示的内容。我认为您不能使用 RowFilter,因为您没有持久的 DataTable 【参考方案1】:

一遍又一遍地创建New DB 对象会妨碍您。如果DataAdapter 是表单级别的变量,您将需要编写更少的代码:

Public Class Form1
    ' declare some persistant DB objects
    Private myDT As DataTable
    Private myDA As OleDbDataAdapter
    Private myStudentsDataView As DataView

    Private dbConnStr As String = "(your connection string)"

这些只是声明的,没有它们的实例(没有New)。但是在哪里声明它们决定了Scope。它们将一直存在,直到表单关闭(或者您用Dim 和/或New 覆盖它们)。表单加载:

' initialize the objects
Dim sql = "SELECT A, B, C, D... FROM Students"

' this is the ONLY place you use NEW 
' with these objects
myDT = New DataTable()

' The Adapter can create its own Connection 
'     and SelectCommand
myDA = New OleDbDataAdapter(sql, dbConnStr)

Dim myCB As New OleDbCommandBuilder(da)

' "teach" the DA how to Update and Add:
myDA.UpdateCommand = myCB.GetUpdateCommand
myDA.InsertCommand = myCB.GetInsertCommand
myDA.DeleteCommand = myCB.GetDeleteCommand

myDA.Fill(myDT)
myDA.FillSchema(myDT, SchemaType.Source)

myStudentsDataView = myDT.DefaultView
dgvStudents.DataSource = myStudentsDataView

DataAdapter 需要一个连接对象才能工作,但正如评论所述,适配器可以创建自己的,而不是显式创建一个。它将根据需要打开和关闭它。 SelectCommand 也是如此 - 它将根据传递的 SELECT SQL 语句创建自己的。

请注意,最好按照您希望列在DataTable 中出现的顺序指定每一列。重要的是最后 that DataAdapter 知道如何删除、插入和更新行。只要您不销毁或替换它,您就不必编写任何 SQL 来添加或更改行!

在大多数情况下,DataTable 用作 DGV 的 DataSource

myDGV.DataSource = myDT 

DGV 将创建所需的列并将数据显示为行。当用户输入单元格时,这些更改会反映在 DataTable 中,因此无需任何代码将其恢复。

如果用户编辑DataGridView 中的数据,您只需将更改发送回数据库:

myDa.Update(myDT)

在这种情况下,根据前面的问题,数据来自文本控件而不是 DGV。所以:

Private Sub AddStudent()
    ' no need to (RE)create DataAdapter

    ' add the data to a new row:
    Dim dr = myDT.NewRow
    dr.Item("FirstName") = textbox1.text
    dr.Item("LastName") = textbox2.text
    ' etc etc

    ' add the new row to the datatable
    myDT.Rows.Add(dr)
   ' with a persistent DA, this is all you need to add a row:
   myDA.Update(myDT)
End Sub

我们“教”了DataAdapter 如何在表单加载中更新一行,因此实际更新数据库(一旦数据在 DT 中)只需一行代码:myDA.Update(myDT)

DataTable 跟踪每一行是新的、更改的还是删除的,因此myDA.Update(myDT) 对每一行采取适当的操作。如果系统是多用户的,你可以接受其他用户的更改:

myDa.Fill(myDT)

搜索也很简单:

Private Sub Search(txt As String)
    myStudentsDataView.RowFilter = String.Format("LastName = '0'", txt)

要删除过滤器:

myStudentsDataView = myDT.DefaultView

如果/当您的DataAdapter 无法添加、插入、更新或删除时,这意味着您在某处创建了一个New。不要那样做。同样,myDataView 将显示 myDT 中的任何内容,直到您创建新的 DT 或 DV 或更改 RowFilter

【讨论】:

会的。非常感谢。 很好的答案 plutonix。我以前也从你那里学会了使用 Using。但是根据您上面的指南,只有一个问题。如果数据库包含至少 2k 行记录,应用程序在将新更改更新回数据库时会开始滞后吗? @Student 通常 2k 行非常小。数据适配器很智能——它会更新新的、更改的或删除的行;所以区别是发送了许多小的更改,或者一批几个。 @Plutonix 我明白了。所以建议使用 dataadapter 来更新它而不是查询新的更新字符串,对吗?我想我会花一整夜把它改成你上面的例子:) 可以更好、更简单、更少的数据库流量。这取决于应用程序。简单地添加/编辑基础项目的应用程序的一部分可以使用它;将多个表连接在一起的另一部分(例如 Order、OrderItems、ServiceLineItem 等)无法使用它。因此,对于多个表,这取决于它们如何/是否相关;简单的标题细节仍然可以工作,而不是 DataSet 我通常有 2 个不同的类在事务中处理每个类。如果基本查询是 SELECT *... 并且代码在删除、更改后重新运行该查询,则适配器可能更有效。

以上是关于通过 datagridview 搜索值的主要内容,如果未能解决你的问题,请参考以下文章

通过过滤器搜索在datagridview中显示多个值

按 datagridview1 column1 值搜索

C# 如何使datagridview中的单元格处于可编辑

DataGridView数据绑定任意对象的数组

DataGridView 行列的隐藏和删除

Form DataGridView绑定BindingSource的几种方式