任何人都可以查看下面的代码,并告知这有什么问题吗?
我试图将值插入MS Access数据库。编译器不会抛出任何错误,但值不会插入表中。
代码:
Private Sub btnSignInOK_Click(sender As Object, e As EventArgs) Handles btnSignInOK.Click
uniqid = "1"
Try
Dim ConnSignIn As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Resources\DBpPNRGENERATORDATA.accdb;Persist Security Info=True")
Dim CmdSignIn As New OleDb.OleDbCommand
If Not ConnSignIn.State = ConnectionState.Open Then
ConnSignIn.Open()
End If
CmdSignIn.Connection = ConnSignIn
CmdSignIn.CommandText = "DELETE TEMPSIGNIN.* FROM TEMPSIGNIN WHERE IDENTIFIER='" + uniqid + "'"
CmdSignIn.ExecuteNonQuery()
CmdSignIn.CommandText = "INSERT INTO TEMPSIGNIN(IDENTIFIER,EPR,Partition,Host)VALUES('" & uniqid & "','" & tbSigninEPR.Text & "','" & cbSignInPartition.Text & "','" & tbSignInAl.Text & "')"
CmdSignIn.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
答案 0 :(得分:1)
DELETE
命令不太正确。您不需要在命令中指定列,因为您要删除行而不是列:
DELETE FROM [TableName]
接下来,您应该在执行SQL命令时使用参数。这是为了减少语法问题,但更重要的是停止SQL注入。有关详细信息,请参阅Bobby Tables。我在使用参数时在SQL命令中使用?
占位符。我还指定了数据类型,因此请考虑使用OleDbParameter Constructor (String, OleDbType)添加参数。
我还会考虑实施Using:
托管资源由.NET Framework垃圾收集器(GC)处理,无需您进行任何额外编码。对于托管资源,您不需要使用“使用”块。但是,您仍然可以使用“使用”块来强制处理受管资源,而不是等待垃圾回收器。
您可以检查ExecuteNonQuery()返回的值,以查看在插入新行之前是否删除了该行。
所有代码看起来都像这样:
uniqid = "1"
Dim rowDeleted As Boolean
Using con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Resources\DBpPNRGENERATORDATA.accdb;Persist Security Info=True")
Using cmd As New OleDbCommand("DELETE FROM [TEMPSIGNIN] WHERE [IDENTIFIER] = ?", con)
con.Open()
cmd.Parameters.Add("@Id", OleDbType.Integer).Value = uniqid
rowDeleted = cmd.ExecuteNonQuery() = 1
End Using
If rowDeleted Then
Using cmd As New OleDbCommand("INSERT INTO [TEMPSIGNIN] ([IDENTIFIER], [EPR], [Partition], [Host]) VALUES (?, ?, ?, ?)", con)
cmd.Parameters.Add("@Id", OleDbType.[Type]).Value = uniqid
cmd.Parameters.Add("@EPR", OleDbType.[Type]).Value = tbSigninEPR.Text
cmd.Parameters.Add("@Partition", OleDbType.[Type]).Value = cbSignInPartition.Text
cmd.Parameters.Add("@Host", OleDbType.[Type]).Value = tbSignInAl.Text
cmd.ExecuteNonQuery()
End Using
End If
End Using
请注意,我使用了
OleDbType.[Type]
。您需要将[Type]
替换为您在数据库中使用的数据类型。
答案 1 :(得分:0)
如上所述,DELETE SQL的语法错误。因此,当数据库尝试执行它时,它会失败,因此INSERT永远不会运行。将DELETE更改为:
CmdSignIn.CommandText = "DELETE FROM TEMPSIGNIN WHERE IDENTIFIER='" + uniqid + "'"
此外,您应该学习如何使用SQL参数,而不是使用字符串连接来创建SQL字符串。使用参数你的DELETE查询变得类似(这不是100%,它不在我的头顶)
CmdSignIn.CommandText = "DELETE FROM TEMPSIGNIN WHERE IDENTIFIER=@ID"
CmdSignIn.Parameters.Add("@ID", uniqid)
CmdSignIn.ExecuteNonQuery()
答案 2 :(得分:0)
好的,关注为什么没有抛出任何异常,无论使用何种语法。您确定要定位正确的物理数据库吗?
如果目标是正确的数据库,如果数据库在解决方案资源管理器中然后选择数据库,选择属性,检查属性“复制到输出目录”,默认为“始终复制”,如果您有此设置,则在每个构建数据库时在项目文件夹中覆盖app文件夹目录中的数据库,因此不会有任何更改。
旁注: 根据目前提供的建议,这是一个需要考虑的模式。将所有数据库操作放在它自己的类中。下面的类是简单的,读取,更新,添加和删除MS-Access数据库表客户(对于此示例)主键,公司名称和联系人姓名。
它自己的函数中的每个操作都有错误处理,如果失败,你可以返回异常(我只是使用此示例的异常消息)。
使用BindingSource,因为此组件在遍历数据绑定控件(如TextBoxes和/或DataGridView)时可以更轻松。
表单代码在DataGridView中显示数据,有一个用于删除当前记录的按钮和一个用于添加新记录的按钮(我省略了断言以查看TextBoxes是否有数据)。我使用两个TextBox控件来获取插入记录的信息。
表格代码
Public Class StackOverFlowForm1
Private Operations As New Sample2
Private bsCustomers As New BindingSource
Private Sub StackOverFlowForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ops As New Sample2
If ops.LoadCustomers Then
bsCustomers.DataSource = ops.CustomersDataTable
DataGridView1.DataSource = bsCustomers
Else
MessageBox.Show($"Failed to load table data{Environment.NewLine}{ops.Exception.Message}")
End If
End Sub
Private Sub cmdDeleteCurrent_Click(sender As Object, e As EventArgs) Handles cmdDeleteCurrent.Click
If bsCustomers.Current IsNot Nothing Then
Dim ops As New Sample2
Dim currentIdentifier As Integer = CType(bsCustomers.Current, DataRowView).Row.Field(Of Integer)("Identifier")
If Not ops.DeleteCustomer(currentIdentifier) Then
MessageBox.Show($"Failed to remove customer: {ops.Exception.Message}")
Else
bsCustomers.RemoveCurrent()
End If
End If
End Sub
Private Sub cmdInsert_Click(sender As Object, e As EventArgs) Handles cmdInsert.Click
Dim ops As New Sample2
Dim newId As Integer = 0
If ops.AddNewRow(txtCompanyName.Text, txtContact.Text, newId) Then
CType(bsCustomers.DataSource, DataTable).Rows.Add(New Object() {newId, txtCompanyName.Text, txtContact.Text})
Else
MessageBox.Show($"Failed to add customer: {ops.Exception.Message}")
End If
End Sub
End Class
然后我们有一个数据库操作类。该数据库位于app文件夹中。
Public Class Sample2
Private Builder As New OleDbConnectionStringBuilder With
{
.Provider = "Microsoft.ACE.OLEDB.12.0",
.DataSource = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Database1.accdb")
}
Private mExceptiom As Exception
''' <summary>
''' Each method when executed, if there is an exception thrown
''' then mException is set and can be read back via Exception property
''' only when a method returns false.
''' </summary>
''' <returns></returns>
Public ReadOnly Property Exception As Exception
Get
Return mExceptiom
End Get
End Property
''' <summary>
''' Container for data read in from a database table
''' </summary>
''' <returns></returns>
Public Property CustomersDataTable As DataTable
Public Function LoadCustomers() As Boolean
If Not IO.File.Exists(Builder.DataSource) Then
Return False
End If
Try
CustomersDataTable = New DataTable
Using cn As New OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDbCommand With {.Connection = cn}
cmd.CommandText = "SELECT Identifier, CompanyName, ContactTitle FROM Customers"
cn.Open()
CustomersDataTable.Load(cmd.ExecuteReader)
CustomersDataTable.DefaultView.Sort = "CompanyName"
CustomersDataTable.Columns("Identifier").ColumnMapping = MappingType.Hidden
End Using
End Using
Return True
Catch ex As Exception
mExceptiom = ex
Return False
End Try
End Function
''' <summary>
''' Delete a customer by their primary key
''' </summary>
''' <param name="CustomerId"></param>
''' <returns></returns>
Public Function DeleteCustomer(ByVal CustomerId As Integer) As Boolean
Dim Success As Boolean = True
Dim Affected As Integer = 0
Try
Using cn As New OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDbCommand With {.Connection = cn}
cmd.CommandText = "DELETE FROM Customers WHERE Identifier = @Identifier"
cmd.Parameters.AddWithValue("@Identifier", CustomerId)
cn.Open()
Affected = cmd.ExecuteNonQuery()
If Affected = 1 Then
Success = True
End If
End Using
End Using
Catch ex As Exception
Success = False
mExceptiom = ex
End Try
Return Success
End Function
Public Function UpdateCustomer(ByVal CustomerId As Integer, ByVal CompanyName As String, ByVal ContactName As String) As Boolean
Dim Success As Boolean = True
Dim Affected As Integer = 0
Try
Using cn As New OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDbCommand With {.Connection = cn}
cmd.CommandText = "UPDATE Customer SET CompanyName = @CompanyName, ContactName = @ContactName WHERE Identifier = @Identifier"
cmd.Parameters.AddWithValue("@CompanyName", CompanyName)
cmd.Parameters.AddWithValue("@ContactName", ContactName)
cmd.Parameters.AddWithValue("@Identifier", ContactName)
cn.Open()
Affected = cmd.ExecuteNonQuery()
If Affected = 1 Then
Success = True
End If
End Using
End Using
Catch ex As Exception
Success = False
mExceptiom = ex
End Try
Return Success
End Function
''' <summary>
''' Add new row, if successful provide the new record's primary key
''' </summary>
''' <param name="Name"></param>
''' <param name="ContactName"></param>
''' <param name="Identfier"></param>
''' <returns></returns>
Public Function AddNewRow(ByVal Name As String, ByVal ContactName As String, ByRef Identfier As Integer) As Boolean
Dim Success As Boolean = True
Try
Using cn As New OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDbCommand With {.Connection = cn}
cmd.CommandText = "INSERT INTO Customers (CompanyName,ContactName) Values(@CompanyName,@ContactName)"
cmd.Parameters.AddWithValue("@CompanyName", Name)
cmd.Parameters.AddWithValue("@ContactName", ContactName)
cn.Open()
Dim Affected As Integer = cmd.ExecuteNonQuery()
If Affected = 1 Then
cmd.CommandText = "Select @@Identity"
Identfier = CInt(cmd.ExecuteScalar)
End If
End Using
End Using
Catch ex As Exception
Success = False
mExceptiom = ex
End Try
Return Success
End Function
End Class