INSERT 和 SELECT 语句的组合导致 VB 中的错误
Combination of INSERT and SELECT statement causes error in VB
这是我的 SQL 服务器存储过程
ALTER PROC [dbo].[insRequestVote]
@fkRequest int,
@fkOrganisation int,
@fkUser int
AS
IF NOT Exists(SELECT 1 FROM [dbo].[tblRequestVote]
WHERE [fkRequest] = @fkRequest
AND [fkOrganisation] = @fkOrganisation
AND [fkUser] = @fkUser)
BEGIN
/* This user from this organisation has not yet voted for this request */
INSERT INTO [dbo].[tblRequestVote] ([fkRequest], [fkOrganisation],[fkUser], [DateStamp])
VALUES (@fkRequest, @fkOrganisation, @fkUser, GetDate());
SELECT
'Inserted' AS VoteResult;
END
ELSE
SELECT 'You have already voted for this SR' AS VoteResult;
当我在 T-SQL 中 运行 时,它工作得很好,例如
insRequestVote 1, 4, 23
将 return 所需的短语。但是,当我从 VB.NET 调用存储过程时,它只将记录写入 table,但不会 return 短语。
后面的代码:
Dim ADOConn As New ADODB.Connection
ADOConn.ConnectionString = WFConnectionString
If (ADOConn.State <> ConnectionState.Open) Then ADOConn.Open()
Dim ADORecSet As New ADODB.Recordset
Dim sSql As String = ""
Try
'----// Save the Vote for the SR
sSql = "dbo.insRequestVote " & row.Cells(0).Text & "," & row.Cells(1).Text & "," & row.Cells(2).Text
ADORecSet = ADOConn.Execute(sSql)
If Not ADORecSet.EOF Then
If ADORecSet.Fields("VoteResult").Value = "Inserted" Then
gridSRs.DataBind()
row.Cells(4).Text = "1"
End If
End If
ADORecSet.Close()
Catch GenEx As Exception
'----- Catch-all
LogAction(Session("WhoAmI"), GenEx.Message, "Error")
Finally
ADOConn.Close()
ADOConn = Nothing
End Try
在 "If Not ADORecSet.EOF Then" 语句之前一切正常,它会跳转到异常行。异常消息是
Operation is not allowed when the object is closed.
我的问题是:为什么特定模式在所有情况下都有效,除非我在一个存储过程中组合了 INSERT 和 SELECT?
我们从哪里开始...您的代码充满了反模式。您应该阅读有关正确使用 ado 的内容,我们转向更简单的东西,例如 ORM。除此之外:
从不 根据用户输入动态构建要在 SQL 中执行的字符串。永远,永远,永远使用参数化查询。否则我可以从你的文本框中删除你所有的数据库表,这很简单。
由于这是一个存储过程,您应该将命令类型设置为该类型,而不是使用文本。否则这会导致 return 值出现异常,这是不好的做法。
您将其标记为 vb。 Net,但您使用的是旧式 ADO?使用 ADO。 Net which returns datasets, not long deprecated recordsets
知道了!以防万一其他人正在尝试这个,这是我修改后的代码:
Dim SQLConn As New SqlConnection(WFConnectionStringNET)
If (SQLConn.State <> ConnectionState.Open) Then SQLConn.Open()
Dim sSql As String = ""
Try
'----// Save the Vote for the SR
sSql = "dbo.insRequestVote " & Mid(row.Cells(0).Text, 2, InStr(row.Cells(0).Text, ":") - 2) & "," &
Session("ThisUserOrganisationID") & "," &
Session("ThisUserID")
Dim sqlCmd As New SqlCommand(sSql, SQLConn)
sqlCmd.Parameters.Add("@fkRequest", SqlDbType.Int).Value = Mid(row.Cells(0).Text, 2, InStr(row.Cells(0).Text, ":") - 2)
sqlCmd.Parameters.Add("@fkOrganisation", SqlDbType.Int).Value = Session("ThisUserOrganisationID")
sqlCmd.Parameters.Add("@fkUser", SqlDbType.Int).Value = Session("ThisUserID")
Dim sqlDR As SqlDataReader = sqlCmd.ExecuteReader()
While sqlDR.Read()
If sqlDR("VoteResult") = "Inserted" Then
gridSRs.DataBind()
row.Cells(4).Text = "1"
End If
End While
sqlDR.Close()
LogAction(Session("WhoAmI"), "Voted for SR " & row.Cells(5).Text)
Catch GenEx As Exception
'-----// Catch-all
LogAction(Session("WhoAmI"), GenEx.Message, "Error")
Finally
SQLConn.Close()
SQLConn = Nothing
End Try
这是我的 SQL 服务器存储过程
ALTER PROC [dbo].[insRequestVote]
@fkRequest int,
@fkOrganisation int,
@fkUser int
AS
IF NOT Exists(SELECT 1 FROM [dbo].[tblRequestVote]
WHERE [fkRequest] = @fkRequest
AND [fkOrganisation] = @fkOrganisation
AND [fkUser] = @fkUser)
BEGIN
/* This user from this organisation has not yet voted for this request */
INSERT INTO [dbo].[tblRequestVote] ([fkRequest], [fkOrganisation],[fkUser], [DateStamp])
VALUES (@fkRequest, @fkOrganisation, @fkUser, GetDate());
SELECT
'Inserted' AS VoteResult;
END
ELSE
SELECT 'You have already voted for this SR' AS VoteResult;
当我在 T-SQL 中 运行 时,它工作得很好,例如
insRequestVote 1, 4, 23
将 return 所需的短语。但是,当我从 VB.NET 调用存储过程时,它只将记录写入 table,但不会 return 短语。
后面的代码:
Dim ADOConn As New ADODB.Connection
ADOConn.ConnectionString = WFConnectionString
If (ADOConn.State <> ConnectionState.Open) Then ADOConn.Open()
Dim ADORecSet As New ADODB.Recordset
Dim sSql As String = ""
Try
'----// Save the Vote for the SR
sSql = "dbo.insRequestVote " & row.Cells(0).Text & "," & row.Cells(1).Text & "," & row.Cells(2).Text
ADORecSet = ADOConn.Execute(sSql)
If Not ADORecSet.EOF Then
If ADORecSet.Fields("VoteResult").Value = "Inserted" Then
gridSRs.DataBind()
row.Cells(4).Text = "1"
End If
End If
ADORecSet.Close()
Catch GenEx As Exception
'----- Catch-all
LogAction(Session("WhoAmI"), GenEx.Message, "Error")
Finally
ADOConn.Close()
ADOConn = Nothing
End Try
在 "If Not ADORecSet.EOF Then" 语句之前一切正常,它会跳转到异常行。异常消息是
Operation is not allowed when the object is closed.
我的问题是:为什么特定模式在所有情况下都有效,除非我在一个存储过程中组合了 INSERT 和 SELECT?
我们从哪里开始...您的代码充满了反模式。您应该阅读有关正确使用 ado 的内容,我们转向更简单的东西,例如 ORM。除此之外:
从不 根据用户输入动态构建要在 SQL 中执行的字符串。永远,永远,永远使用参数化查询。否则我可以从你的文本框中删除你所有的数据库表,这很简单。
由于这是一个存储过程,您应该将命令类型设置为该类型,而不是使用文本。否则这会导致 return 值出现异常,这是不好的做法。
您将其标记为 vb。 Net,但您使用的是旧式 ADO?使用 ADO。 Net which returns datasets, not long deprecated recordsets
知道了!以防万一其他人正在尝试这个,这是我修改后的代码:
Dim SQLConn As New SqlConnection(WFConnectionStringNET)
If (SQLConn.State <> ConnectionState.Open) Then SQLConn.Open()
Dim sSql As String = ""
Try
'----// Save the Vote for the SR
sSql = "dbo.insRequestVote " & Mid(row.Cells(0).Text, 2, InStr(row.Cells(0).Text, ":") - 2) & "," &
Session("ThisUserOrganisationID") & "," &
Session("ThisUserID")
Dim sqlCmd As New SqlCommand(sSql, SQLConn)
sqlCmd.Parameters.Add("@fkRequest", SqlDbType.Int).Value = Mid(row.Cells(0).Text, 2, InStr(row.Cells(0).Text, ":") - 2)
sqlCmd.Parameters.Add("@fkOrganisation", SqlDbType.Int).Value = Session("ThisUserOrganisationID")
sqlCmd.Parameters.Add("@fkUser", SqlDbType.Int).Value = Session("ThisUserID")
Dim sqlDR As SqlDataReader = sqlCmd.ExecuteReader()
While sqlDR.Read()
If sqlDR("VoteResult") = "Inserted" Then
gridSRs.DataBind()
row.Cells(4).Text = "1"
End If
End While
sqlDR.Close()
LogAction(Session("WhoAmI"), "Voted for SR " & row.Cells(5).Text)
Catch GenEx As Exception
'-----// Catch-all
LogAction(Session("WhoAmI"), GenEx.Message, "Error")
Finally
SQLConn.Close()
SQLConn = Nothing
End Try