【问题标题】:Select from Service Based Database not finding any values without a selection in a DataGridView (WinFormsApp VB .Net Framework)从基于服务的数据库中选择没有在 DataGridView (WinFormsApp VB .Net 框架)中选择没有找到任何值
【发布时间】:2021-05-27 13:24:59
【问题描述】:

我对 VB .Net 和数据库很陌生,所以我不确定我使用的是哪个 SQL 版本。到目前为止,我的大部分编码都是使用 VBA 完成的。

我在“WinFormsApp”项目中添加了一个“基于服务的数据库”,并创建了一个包含 3 列的表:

CREATE TABLE [dbo].[employees] (
    [id]   INT           IDENTITY (1, 1) NOT NULL,
    [nr]   VARCHAR (MAX) NULL,
    [name] TEXT          NULL,
    PRIMARY KEY CLUSTERED ([id] ASC)
);

之后我为创建的表添加了一个数据集。

在此之后,我向我的项目添加了一个新表单,并向其中添加了一些控件,包括两个用于 Dataentry 的 TextBoxes 和一个用于显示已保存数据的 DataGridView。在 Form_Load 上,我使用以下代码填充 DataGridView:

    Private Sub UpdateGridView()

        'Loading the data into the GridView
        '---------------------------------------
        Dim Conn As SqlConnection = New SqlConnection
        Dim ADP As SqlDataAdapter
        Dim DS As DataSet = New DataSet

        Conn.ConnectionString = My.Settings.DBConnEmployees
        ADP = New SqlDataAdapter("SELECT * FROM employees", Conn)
        ADP.Fill(DS)

        Me.DataGridView_Employees.DataSource = DS.Tables(0)
        '---------------------------------------

        'Hidding the ID Col
        Me.DataGridView_Employees.Columns(0).Visible = False

    End Sub

我还在 Form_Load 中设置了一些不相关的变量和文本框(因为经过几个小时的反复试验后我无法找到错误,我将其包括在内。也许我忽略了一些东西):

    Private Sub NewEmployee()

        'Reseting the Variables
        DataGridIndex = -1
        EmployeeId = 0
        EmployeeNr = String.Empty
        EmployeeName = String.Empty

        'Writing to TBs
        Me.tbNr.Text = EmployeeNr
        Me.tbName.Text = EmployeeName

        'Select Nothing
        Me.DataGridView_Employees.CurrentCell = Nothing

        'Changing Btn Desc
        Me.btnSaveEmployee.Text = "Neuen Mitarbeiter speichern"

    End Sub

我手动输入表格的测试数据填写没有问题。通过代码在表中插入、更新删除操作非常完美。

在 DataGrivView_CellDoubleClick 上,我将 GridView 的一些数据读入 TextBoxes 以对其进行编辑:

    Private Sub DataGridView_Employees_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView_Employees.CellDoubleClick
        If e.RowIndex <> -1 Then

            'Loading selected Data
            DataGridIndex = e.RowIndex
            EmployeeId = Me.DataGridView_Employees.Rows(DataGridIndex).Cells(0).Value
            EmployeeNr = Me.DataGridView_Employees.Rows(DataGridIndex).Cells(1).Value
            EmployeeName = Me.DataGridView_Employees.Rows(DataGridIndex).Cells(2).Value

            'Write to TBs
            Me.tbNr.Text = EmployeeNr
            Me.tbName.Text = EmployeeName


            'Changing btn
            Me.btnSaveEmployee.Text = "Änderungen speichern"

        End If
    End Sub

为了防止用户使用 nr 两次,我想检查 nr 是否已保存在表中。然而,这就是问题开始的地方。 SQLCommand 只找到我在 GridView 中双击的行。这很奇怪,因为它们之间不应该有任何联系。此后我尝试检查 nr:

    Private Function EmployeeNrInUse(id As Integer, nr As String) As Boolean

        Dim Query As String = String.Empty
        Dim Result
        Dim Response As Boolean = True

        'Checking for nr
        '---------------------------------------
        Query = "SELECT * FROM employees WHERE nr=@nr"

        Using Conn = New SqlConnection(My.Settings.DBConnEmployees)
            Using Comm = New SqlCommand()
                With Comm
                    .Connection = Conn
                    .CommandType = CommandType.Text
                    .CommandText = Query
                    .Parameters.AddWithValue("@nr", nr)
                End With
                Try
                    Conn.Open()
                    Result = Comm.ExecuteScalar
                    Response = Not IsNothing(Result)
                Catch ex As SqlException
                    MsgBox(ex.Message.ToString, vbOKOnly + vbCritical)
                End Try
            End Using
        End Using
        '---------------------------------------

        'Return
        Return Response

    End Function

结果总是什么都不返回,除非我之前双击一个数据条目,然后它会找到它自己的行(如果 nr 匹配)但仅此而已,没有找到其他匹配的 nr。

如果我忘记提及关键数据,请通知我,因为这是我在论坛上的第一个问题 :) (另外请原谅任何拼写错误等,因为英语不是我的母语)提前感谢您的帮助!

编辑:
这就是函数 EmployeeNrInUse 的调用方式(在 Button_Clicked 上调用):

    Private Sub SaveEmployeeToDB(id As Integer, nr As String, name As String)

        Dim Query As String = String.Empty

        'Adding new Employee / Editing existing
        '---------------------------------------

        If EmployeeNrInUse(id, nr) Then
            MsgBox("Nr. bereits in verwendung.", vbOKOnly + vbExclamation)
            Exit Sub
        End If

        If EmployeeId = 0 Then
            Query = "INSERT INTO employees (nr, name) VALUES (@nr, @name)"
        Else
            Query = "UPDATE employees SET nr=@nr, name=@name WHERE id=@id"
        End If

        Using Conn As New SqlConnection(My.Settings.DBConnEmployees)
            Using Comm As New SqlCommand()
                With Comm
                    .Connection = Conn
                    .CommandType = CommandType.Text
                    .CommandText = Query
                    .Parameters.AddWithValue("@id", id) 'Wird nur bei änderung verwendet
                    .Parameters.AddWithValue("@nr", nr)
                    .Parameters.AddWithValue("@name", name)
                End With

                Try
                    Conn.Open()
                    Comm.ExecuteNonQuery()
                    UpdateGridView()
                    If EmployeeId = 0 Then
                        MsgBox("Neuen Mitarbeiter gespeichert.", vbOKOnly + vbInformation)
                    Else
                        MsgBox("Bestehenden Mitarbeiter aktualisiert.", vbOKOnly + vbInformation)
                    End If
                    NewEmployee()
                Catch ex As SqlException
                    MsgBox(ex.Message.ToString, vbOKOnly + vbCritical)
                End Try
            End Using
        End Using
        '---------------------------------------

    End Sub

【问题讨论】:

  • 你能显示你的函数EmployeeNrInUse是如何被调用的代码吗?
  • @TimothyG。我已将其添加到我的问题中。
  • 可能是ExecuteScalar 返回“结果集中第一行的第一列,如果结果集为空,则返回空引用(在 Visual Basic 中为空)”。由于您正在执行SELECT *,因此返回的第一列将是表中的第一列。您应该在 ExecuteScalar 命令中明确说明要返回的列 - 我无法确定返回的第一列是什么,但我想知道它是否为空/错误
  • [name] TEXT NULL, 不不不不不!这种数据类型已被弃用近 20 年; varchar(max) 是适当的替换类型。但是没有名字那么长,我怀疑 NR 列也应该是 varchar(max) 。并且这些列中的至少一个不应为空(可能两者都为空)。如果 NR 应该是唯一的,那么让 db 引擎处理它。
  • 不要使用addwithvalue

标签: sql sql-server vb.net


【解决方案1】:

问题是由手动将值输入数据库引起的。在复制 nr 时,换行符会潜入值中,因此仅检查 nr 而不是 nr 和换行符不会产生任何结果。正确输入数据已解决问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-10
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-20
    • 1970-01-01
    相关资源
    最近更新 更多