如何 show/display 在数据网格视图中保存数据
How to show/display saved data on data grid view
我目前正在尝试使用 vb.net 为 IMS(库存管理系统)编写 material 预订模块。这是我已经完成的部分代码
Public Class frmINBKG
Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click
Me.Close()
End Sub
Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
Call ClearDetails()
End Sub
Private Function SaveRecord() As Boolean
Dim strSQL As String
strSQL = "INSERT INTO INBKG_TBL ("
strSQL &= "INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, "
strSQL &= "INBKG_BKGQT, INBKG_STSFG) "
strSQL &= "VALUES ('" & txtBKGID.Text & "', '" & gfSQLDate(dtBKGDT.Value) & "', '" & txtUSRID.Text & "', '" & txtBKGMAT.Text & "', "
strSQL &= "" & numBKGQT.Value & ", '1')"
Call DBExecute(strSQL)
End Function
Private Sub ClearDetails()
txtBKGID.Text = String.Empty
dtBKGDT.Value = Date.Today
txtUSRID.Text = String.Empty
txtBKGMAT.Text = String.Empty
numBKGQT.Value = 0
numRECID.Value = 0
End Sub
Private Sub RefreshGrid()
Dim strSQL As String
Dim dt As DataTable
Dim i As Integer
strSQL = "SELECT INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, "
strSQL &= "INBKG_BKGQT, INBKG_STSFG "
strSQL &= "FROM INBKG_TBL "
strSQL &= "WHERE INBKG_STSFG IN ('1', '2')"
dt = ExecProc(strSQL)
*show grid
End Sub
Private Sub frmINEADJ_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
Dim blnChildFormExists As Boolean
For Each ChildForm As Form In Me.ParentForm.MdiChildren
If ChildForm.Name <> Me.Name Then
blnChildFormExists = True
Exit For
End If
Next
If Not blnChildFormExists Then Me.ParentForm.Controls("Panel1").Visible = True
End Sub
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Call SaveRecord()
Call RefreshGrid()
End Sub
Private Sub btnRefresh_Click(sender As Object, e As EventArgs) Handles btnRefresh.Click
Call RefreshGrid()
End Sub
End Class
*show 网格线是我想有一个代码允许我在数据网格视图上显示任何已保存数据的地方。我是 vb.net 的新手,所以我被告知要参考其他模块以获取示例,但其中大部分不是我需要的或者不兼容。我目前正在使用 Visual Studio 2019 和 Microsoft SQL Server Management Studio,欢迎提供任何答案或建议。
我会避免使用 DataTables 并创建一个对象 class,其属性代表 table。将每个对象添加到 BindingList 并将其用作网格的数据源。网格随后会在发生任何更改时自动更新。
此外,为避免 SQL 注入攻击,请始终使用 SqlParameters。
我的建议是使用Entity Framework(工具 -> 管理 NuGet 包 -> 管理 NuGet 包的解决方案。6.4.4 应该是最新版本)。实体将您的数据库 table 视为 类。
我举个例子
'Create your entity object
Dim context as New MyProjectEntity
'Query
Dim myGridviewDataSource = context.myTable.Tolist
Me.gridview1.Properties.DataSource = myGridviewDataSource
这是一个简单的例子。您的 gridview 将在 header 中包含 myTable 的列名,数据将自动显示,ID 列将被隐藏。您最终可以从设计器 window (SHIFT+F7) 中设置列。这真的很好,因为您可以简单地使用 lambda 表达式进行查询。假设您有一个名为 Students 的 table 和一个名为 studentName 的列,并且您只想获取 studentName = John 的 Students。您可以像这样简单地查询:
Dim myGridviewDataSource = context.Students.Where(function(x) x.Name.equals("John")).Tolist
此外,如果您有外键,只需继续设计器 window、运行 gridview 设计器,并在列字段名中完成操作。例如,对于每个学生,您都分配了一个教师,因此您将 teacherID 列作为学生中的外键,这是 table 教师的主键,但您希望在 gridview 上看到教师的姓名.所以继续设计器 window,在针对教师姓名的列的字段名上,你给它的值
Teacher.teacherName
teacherName 当然必须是 Teacher table 中列的名称。请记住,您需要在 Microsoft SQL Server Management Studio 中指定外键!实体将完成剩下的工作
只需重置 DataGridView
的 DataSource
。 INBKG_STSFG真的是数据库中的字符串字段吗?
Private Sub RefreshGrid()
Dim strSQL = "SELECT INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, INBKG_BKGQT, INBKG_STSFG
FROM INBKG_TBL
WHERE INBKG_STSFG IN ('1', '2');"
Dim dt = ExecProc(strSQL) 'I assume this method returns a DataTable
DataGridView1.DataSource = Nothing
DataGridView1.DataSource = dt
End Sub
你真正的问题是SaveRecord()
。此方法存在 sql 注入的高风险。当您将用户输入的字符串连接到 sql 字符串中时,服务器可以执行该输入。假设用户在文本框中输入“Drop table”? 总是 使用Parameters
。参数的值不被服务器认为是executable。
vb.net 中的函数需要具有与类型匹配的值的 Return
语句。
顺便说一句,你只需要在非常特殊的情况下使用Call
。不在此代码中。
Private Function SaveRecord() As Boolean
Dim RetVal As Integer
Dim strSQL = "INSERT INTO INBKG_TBL (INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, INBKG_BKGQT, INBKG_STSFG)
VALUES(@ID, @Date, @USRID, @MAT, @QT, @STSFG);"
Using cn As New SqlConnection("Your connection String"),
cmd As New SqlCommand(strSQL, cn)
With cmd.Parameters
.Add("@ID", SqlDbType.VarChar).Value = txtBKGID.Text
.Add("@Date", SqlDbType.Date).Value = gfSQLDate(dtBKGDT).Value
.Add("@USRID", SqlDbType.VarChar).Value = txtUSRID.Text
.Add("@MAT", SqlDbType.VarChar).Value = txtBKGMAT.Text
.Add("@QT", SqlDbType.Int).Value = CInt(numBKGQT.Value)
.Add("@STSFG", SqlDbType.Int).Value = 1
End With
cn.Open()
RetVal = cmd.ExecuteNonQuery
End Using
If RetVal = 1 Then
Return True
End If
Return False
End Function
我不得不猜测字段的数据类型。通常 ID 字段是数字,因此您需要检查所有数据类型并在必要时将值转换为适当的类型。如果 INBKG_BKGID 是标识字段,则您不会将其包含在字段列表中或为其设置参数。服务器会提供。
我目前正在尝试使用 vb.net 为 IMS(库存管理系统)编写 material 预订模块。这是我已经完成的部分代码
Public Class frmINBKG
Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click
Me.Close()
End Sub
Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
Call ClearDetails()
End Sub
Private Function SaveRecord() As Boolean
Dim strSQL As String
strSQL = "INSERT INTO INBKG_TBL ("
strSQL &= "INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, "
strSQL &= "INBKG_BKGQT, INBKG_STSFG) "
strSQL &= "VALUES ('" & txtBKGID.Text & "', '" & gfSQLDate(dtBKGDT.Value) & "', '" & txtUSRID.Text & "', '" & txtBKGMAT.Text & "', "
strSQL &= "" & numBKGQT.Value & ", '1')"
Call DBExecute(strSQL)
End Function
Private Sub ClearDetails()
txtBKGID.Text = String.Empty
dtBKGDT.Value = Date.Today
txtUSRID.Text = String.Empty
txtBKGMAT.Text = String.Empty
numBKGQT.Value = 0
numRECID.Value = 0
End Sub
Private Sub RefreshGrid()
Dim strSQL As String
Dim dt As DataTable
Dim i As Integer
strSQL = "SELECT INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, "
strSQL &= "INBKG_BKGQT, INBKG_STSFG "
strSQL &= "FROM INBKG_TBL "
strSQL &= "WHERE INBKG_STSFG IN ('1', '2')"
dt = ExecProc(strSQL)
*show grid
End Sub
Private Sub frmINEADJ_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
Dim blnChildFormExists As Boolean
For Each ChildForm As Form In Me.ParentForm.MdiChildren
If ChildForm.Name <> Me.Name Then
blnChildFormExists = True
Exit For
End If
Next
If Not blnChildFormExists Then Me.ParentForm.Controls("Panel1").Visible = True
End Sub
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Call SaveRecord()
Call RefreshGrid()
End Sub
Private Sub btnRefresh_Click(sender As Object, e As EventArgs) Handles btnRefresh.Click
Call RefreshGrid()
End Sub
End Class
*show 网格线是我想有一个代码允许我在数据网格视图上显示任何已保存数据的地方。我是 vb.net 的新手,所以我被告知要参考其他模块以获取示例,但其中大部分不是我需要的或者不兼容。我目前正在使用 Visual Studio 2019 和 Microsoft SQL Server Management Studio,欢迎提供任何答案或建议。
我会避免使用 DataTables 并创建一个对象 class,其属性代表 table。将每个对象添加到 BindingList 并将其用作网格的数据源。网格随后会在发生任何更改时自动更新。
此外,为避免 SQL 注入攻击,请始终使用 SqlParameters。
我的建议是使用Entity Framework(工具 -> 管理 NuGet 包 -> 管理 NuGet 包的解决方案。6.4.4 应该是最新版本)。实体将您的数据库 table 视为 类。 我举个例子
'Create your entity object
Dim context as New MyProjectEntity
'Query
Dim myGridviewDataSource = context.myTable.Tolist
Me.gridview1.Properties.DataSource = myGridviewDataSource
这是一个简单的例子。您的 gridview 将在 header 中包含 myTable 的列名,数据将自动显示,ID 列将被隐藏。您最终可以从设计器 window (SHIFT+F7) 中设置列。这真的很好,因为您可以简单地使用 lambda 表达式进行查询。假设您有一个名为 Students 的 table 和一个名为 studentName 的列,并且您只想获取 studentName = John 的 Students。您可以像这样简单地查询:
Dim myGridviewDataSource = context.Students.Where(function(x) x.Name.equals("John")).Tolist
此外,如果您有外键,只需继续设计器 window、运行 gridview 设计器,并在列字段名中完成操作。例如,对于每个学生,您都分配了一个教师,因此您将 teacherID 列作为学生中的外键,这是 table 教师的主键,但您希望在 gridview 上看到教师的姓名.所以继续设计器 window,在针对教师姓名的列的字段名上,你给它的值
Teacher.teacherName
teacherName 当然必须是 Teacher table 中列的名称。请记住,您需要在 Microsoft SQL Server Management Studio 中指定外键!实体将完成剩下的工作
只需重置 DataGridView
的 DataSource
。 INBKG_STSFG真的是数据库中的字符串字段吗?
Private Sub RefreshGrid()
Dim strSQL = "SELECT INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, INBKG_BKGQT, INBKG_STSFG
FROM INBKG_TBL
WHERE INBKG_STSFG IN ('1', '2');"
Dim dt = ExecProc(strSQL) 'I assume this method returns a DataTable
DataGridView1.DataSource = Nothing
DataGridView1.DataSource = dt
End Sub
你真正的问题是SaveRecord()
。此方法存在 sql 注入的高风险。当您将用户输入的字符串连接到 sql 字符串中时,服务器可以执行该输入。假设用户在文本框中输入“Drop table”? 总是 使用Parameters
。参数的值不被服务器认为是executable。
vb.net 中的函数需要具有与类型匹配的值的 Return
语句。
顺便说一句,你只需要在非常特殊的情况下使用Call
。不在此代码中。
Private Function SaveRecord() As Boolean
Dim RetVal As Integer
Dim strSQL = "INSERT INTO INBKG_TBL (INBKG_BKGID, INBKG_BKGDT, INBKG_USRID, INBKG_MATCD, INBKG_BKGQT, INBKG_STSFG)
VALUES(@ID, @Date, @USRID, @MAT, @QT, @STSFG);"
Using cn As New SqlConnection("Your connection String"),
cmd As New SqlCommand(strSQL, cn)
With cmd.Parameters
.Add("@ID", SqlDbType.VarChar).Value = txtBKGID.Text
.Add("@Date", SqlDbType.Date).Value = gfSQLDate(dtBKGDT).Value
.Add("@USRID", SqlDbType.VarChar).Value = txtUSRID.Text
.Add("@MAT", SqlDbType.VarChar).Value = txtBKGMAT.Text
.Add("@QT", SqlDbType.Int).Value = CInt(numBKGQT.Value)
.Add("@STSFG", SqlDbType.Int).Value = 1
End With
cn.Open()
RetVal = cmd.ExecuteNonQuery
End Using
If RetVal = 1 Then
Return True
End If
Return False
End Function
我不得不猜测字段的数据类型。通常 ID 字段是数字,因此您需要检查所有数据类型并在必要时将值转换为适当的类型。如果 INBKG_BKGID 是标识字段,则您不会将其包含在字段列表中或为其设置参数。服务器会提供。