【发布时间】: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