WinForms VB.NET查询基于服务的数据库未选中DataGridView行找不到值
问题原因
- 全局变量取值逻辑错误。你只有在双击DataGridView行的时候才会给全局变量
EmployeeNr赋值,新增/修改时直接在文本框输入内容后,EmployeeNr没有同步更新,导致你调用EmployeeNrInUse校验时传入的nr参数不是当前文本框的实际值,只有之前双击过的行对应的EmployeeNr有正确值,所以只能查到这部分记录。 - 校验查询逻辑不完善。你使用
SELECT *配合ExecuteScalar效率极低,且没有排除当前正在编辑的记录,编辑已有记录时如果不修改nr字段,会误判为重复。 - 可选隐患:本地Service Based Database默认的「复制到输出目录」属性为「始终复制」,每次运行程序时会用项目根目录的原始mdf文件覆盖bin目录下的运行时数据库,导致你之前修改的数据丢失,可能出现查询不到的情况。
AddWithValue隐式类型转换问题:AddWithValue会自动推断参数类型,可能和数据库字段的VARCHAR(MAX)类型不匹配,导致查询条件失效。
解决方法
- 修正参数传递逻辑,调用
SaveEmployeeToDB时直接从文本框取值,不要依赖全局变量:
在保存按钮的点击事件处理函数中,调用SaveEmployeeToDB的代码改成:
SaveEmployeeToDB(EmployeeId, tbNr.Text.Trim(), tbName.Text.Trim())
- 优化
EmployeeNrInUse函数的查询逻辑,排除当前编辑的记录,使用更高效的查询语句,明确指定参数类型:
Private Function EmployeeNrInUse(id As Integer, nr As String) As Boolean ' 空nr不需要校验重复,不需要可以删除这行 If String.IsNullOrWhiteSpace(nr) Then Return False ' 用EXISTS逻辑查询效率更高,无需返回全表数据 Dim Query As String = "SELECT 1 FROM employees WHERE nr=@nr AND id <> @id" Dim Response As Boolean = False Using Conn = New SqlConnection(My.Settings.DBConnEmployees) Using Comm = New SqlCommand() With Comm .Connection = Conn .CommandType = CommandType.Text .CommandText = Query ' 明确指定参数类型,避免AddWithValue的隐式转换问题,-1对应VARCHAR(MAX) .Parameters.Add("@nr", SqlDbType.VarChar, -1).Value = nr .Parameters.Add("@id", SqlDbType.Int).Value = id End With Try Conn.Open() Dim Result = Comm.ExecuteScalar() Response = Not IsNothing(Result) Catch ex As SqlException MsgBox(ex.Message.ToString, vbOKOnly + vbCritical) End Try End Using End Using Return Response End Function
修正本地数据库的复制属性(可选,需要持久化测试数据时操作):
在解决方案资源管理器中找到你的.mdf数据库文件,右键选择「属性」,将「复制到输出目录」属性修改为「如果较新则复制」,避免每次运行都重置数据。可选优化:SQL Server中
TEXT类型已经被弃用,建议将name字段的类型改为VARCHAR(MAX)或者NVARCHAR(MAX),兼容性更好。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

