1

首先,我在 VB 2012 工作。

我在搜索我的数据库时遇到问题。它变得如此缓慢,实际上填充ListView是困扰我的。
我有一个带有 TextChange 事件的文本框。它的即时搜索。因此,当我开始在该文本框中写入内容时,它开始过滤数据库并将数据填充到ListView.

这是代码text boxLoad过程

Private Sub txtID_TextChanged(sender As Object, e As EventArgs) Handles txtID.TextChanged
    Load("SELECT * FROM table WHERE id LIKE '" & txtID.Text & "%'")
End Sub


Private Sub Load(ByVal strQ As String)
    List.Items.Clear()
    cmd = New SqlClient.SqlCommand(strQ, con)
    dr = cmd.ExecuteReader()
    If dr.HasRows = True Then
        While dr.Read
            Dim X As ListViewItem
            X = List.Items.Add(dr(0))
            X.SubItems.Add(dr(2))
            X.SubItems.Add(dr(3))
            X.SubItems.Add(dr(4))
            X.SubItems.Add(dr(1))
            X.SubItems.Add(dr(5))            
        End While
    End If
End Sub

因此,每次我击中一个字母时,它都会调用加载过程。

而且我有这么多数据,而且速度很慢。你能以某种方式帮助我吗?有什么解决办法吗?

4

3 回答 3

2

我不知道您将如何加快速度。连接和查询数据库的开销很大,尤其是与按键或输入单词的速度相比。没有办法在不严重影响正在打字的用户的情况下做到这一点。

相反,我建议您等待用户告诉您他们已经完成输入,然后再进行搜索。如果您尝试做一些花哨的自动完成功能,您将需要将数据缓存到更靠近应用程序而不是数据库的位置。

于 2013-10-03T21:01:39.657 回答
2

您需要创建一个类来保存搜索结果,如下所示:

Public Class SearchResult
    Private _propID As String
    Public Property ID() As String
        Get
            Return _propID
        End Get
        Set
            _propID = Value
        End Set
    End Property

Private _propName As String
    Public Property PropName() As String
        Get
            Return _propName
        End Get
        Set
            _propName = Value
        End Set
    End Property
    ...
End Class

现在您查询数据库以获取要显示在列表视图中的所有结果,并将其存储在 a 中List(Of SearchResult),如下所示:

Private Function Load(ByVal strQ As String) As List(Of SearchResult)
    Dim ListOfResults = New List(Of SearchResult)
    cmd = New SqlClient.SqlCommand(strQ, con)
    dr = cmd.ExecuteReader()
    If dr.HasRows = True Then
        While dr.Read
            Dim X As New SearchResult()
            X.PropID = dr(0)
            X.PropName = dr(1)
            ...            
        End While
    End If
End Sub

您可以像这样调用此代码:

Dim AllSearchResults = Load("SELECT * FROM table WHERE id LIKE '" & txtID.Text & "%'")

现在,当您想要进行搜索时,可以将以下 LINQ 应用于缓存的所有内容列表 ( AllSearchResults),如下所示:

Public Function DoSearch(searchText As String) As List(Of SearchResult)    
    Return From s In AllSearchResults Where s.PropID.Contains(searchText) Select c
End Function

最后,您可以在用户每次按键时调用此 LINQ 过滤,如下所示:

Private Sub txtID_TextChanged(sender As Object, e As EventArgs) Handles txtID.TextChanged
    DoSearch(txtID.Text)
End Sub
于 2013-10-03T21:44:24.923 回答
0

一种将开销降低到相当程度的方法是等待发出查询,直到输入的文本长度为 3 个(或更好的 5 个)字符。除了在极少数情况下寻找“Sab ....”的人之外,所有以“S”开头的客户(或任何这些客户)都非常非常不可能对任何人都有意义或有帮助。人们必须在第一个查询完成并显示之前输入第二个和第三个字符!

为了试图让一个非常糟糕的想法变得不那么糟糕,我会研究一种方法来发出一次查询(如果我真的,真的必须在第一个字符上),然后在随后的击键中过滤这些结果。(ala Aaron 的“缓存数据更接近应用程序”)。

接下来是Select *。我不知道表中有什么,但你真的需要每一列吗?这似乎是某种选择列表,您真的需要 6 个字段来为用户提供选择所需的信息吗?如果表中的列超过 6 个,则立即将查询范围缩小到列表视图中使用的 6 个。一旦他们做出选择,您就可以返回并通过 ID 或其他方式获得所需的确切信息。

我个人会使用更快的控制,但那是主观的。

所有数据库最终都会获取休眠数据。曾经是购物者并且永远不会回来的客户(或其他) - 他们需要在列表中吗?如果某处有 lastorderdate 或 lastupdateddate 列,请构建您的查询以选择过去 XX 个月内活动的那些(如果没有,请查看是否可以添加一个,因为随着数据库变大,问题不会变得更好!)。然后是一个复选框,供用户根据需要扩大范围,例如“查看全部”或其他内容。如果它在另外 80% 的时间内加快了速度,用户就不会拒绝这个想法。

......那些只是我的头顶。

于 2013-10-03T21:52:54.370 回答