这个T-SQL查询出了什么问题:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim SQLData As New System.Data.SqlClient.SqlConnection("Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True")
Dim cmdSelect As New System.Data.SqlClient.SqlCommand("SELECT COUNT(*) FROM Table1 WHERE Name ='" + TextBox1.Text + "'", SQLData)
SQLData.Open()
If cmdSelect.ExecuteScalar > 0 Then
Label1.Text = "You have already voted this service"
Return
End If
Dim con As New SqlConnection
Dim cmd As New SqlCommand
con.Open()
cmd.Connection = con
cmd.CommandText = "INSERT INTO Tabel1 (Name) VALUES('" & Trim(Label1.Text) & "')"
cmd.ExecuteNonQuery()
Label1.Text = "Thank You !"
SQLData.Close()
End Sub
答案 0 :(得分:1)
您的问题是您正在打开连接(SQLData
),忽略它,然后尝试打开新连接(con
)而不给它连接字符串。而不是:
Dim con As New SqlConnection
Dim cmd As New SqlCommand
con.Open()
cmd.Connection = con
你应该:
Dim cmd As New SqlCommand
cmd.Connection = SQLData
此外,在SQL中插入字符串值是非常糟糕的做法。
答案 1 :(得分:0)
我发现有一些错误。首先,(除了SQL注入漏洞之外)是您输入Table1
一次,而Tabel1
则是另一次。虽然这可能是你想要的,但我对此表示怀疑。接下来,您将创建第二个连接。这似乎不需要。使用现有的SQLData
对象而不是con
。您还可以使用以下内容减少从cmd
(包括)声明到ExecuteNonQuery
调用(不包括)的行:
Dim cmd As New SqlCommand("INSERT INTO Tabel1 (Name) VALUES('" & Trim(Label1.Text) & "')", SQLData)
现在回到SQL注入漏洞。如果有人的名字是“詹姆斯·奥布莱恩”(或其他带有撇号的东西)怎么办?
答案 2 :(得分:0)
我建议采用这样的方法:
Protected Function Button1_Click(sender As Object, e As System.EventArgs)
' define and create your one single SqlConnection and protect it by using a "using()....." block
Using _connection As New SqlConnection("Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True")
' define and craete your SqlCommand to count your occurences and make it a proper, parametrized query
Using cmdSelect As New SqlCommand("SELECT COUNT(*) FROM dbo.Table1 WHERE Name = @Name", _connection)
' add the parameter to your SqlCommand, define the datatype and length
cmdSelect.Parameters.Add("@Name", SqlDbType.VarChar, 100)
' set the value for that parameter
cmdSelect.Parameters("@Name").Value = TextBox1.Text.Trim()
' open connection, execute query, set return value
_connection.Open()
If cmdSelect.ExecuteScalar() > 0 Then
Label1.Text = "You have already voted this service"
Return
End If
End Using
' define second query to insert data reusing the existing connection
Using cmdInsert As New SqlCommand("INSERT INTO dbo.Table1(Name) VALUES(@Name)", _connection)
' add the parameter to your SqlCommand, define the datatype and length
cmdInsert.Parameters.Add("@Name", SqlDbType.VarChar, 100)
' set the value for that parameter
cmdInsert.Parameters("@Name").Value = Label1.Text.Trim()
cmdInsert.ExecuteNonQuery()
End Using
_connection.Close()
End Using
Label1.Text = "Thank You !"
End Function
要考虑的要点:
您有一个 SqlConnection
- 这对两个查询都足够好,可以重复使用它!
始终将SqlConnection
,SqlCommand
等一次性对象放入Using.....
块以保护它们并确保它们得到妥善处理
始终使用参数化查询 - 在任何情况下执行 NOT 只是将SQL语句连接在一起 - 这是一个巨大的巨大安全性洞,邀请SQL注入攻击 - 只是不要这样做 - 永远!
如果可以的话,我会尝试将您的UI元素与代码分开 - 尝试将此代码放入一个单独的方法,该方法将从调用者接收字符串值,并返回一个结果字符串在UI上设置(Label1.Text=
)。混合查询数据库并同时设置UI的代码很混乱,导致意大利面条代码 - 尝试将这些内容分开
将您的连接字符串放入web.config
<connectionStrings>
部分并从那里读取 - 在整个代码中没有连接字符串作为字符串文字!