Sql server 将结果集从SQL Server返回到VB.NET应用程序
我需要返回一个由SQL Server存储过程的Sql server 将结果集从SQL Server返回到VB.NET应用程序,sql-server,vb.net,resultset,cursors,Sql Server,Vb.net,Resultset,Cursors,我需要返回一个由SQL Server存储过程的CATCH子句中的数据库错误组成的结果集,但我一直在使用它。我是否需要使用游标来返回结果集?如果需要,那么.NET应用程序中的输出参数的类型声明是什么?我尝试了对象和变量,但没有成功 我还尝试了使用SELECT语句返回的简单方法,它适用于一个存储过程,但不适用于另一个存储过程,如我的CATCH子句中所述: while (@I <= @count) begin BEGIN TRY -- del
CATCH
子句中的数据库错误组成的结果集,但我一直在使用它。我是否需要使用游标来返回结果集?如果需要,那么.NET应用程序中的输出
参数的类型声明是什么?我尝试了对象
和变量
,但没有成功
我还尝试了使用SELECT
语句返回的简单方法,它适用于一个存储过程,但不适用于另一个存储过程,如我的CATCH
子句中所述:
while (@I <= @count)
begin
BEGIN TRY
-- delete all previous rows inserted in @customerRow for previous counts @I
delete from @customerRow
-- this is inserting the current row that we want to save in database
insert into @customerRow
SELECT
[id],[firstname], [lastname], [street], [city],
[phone],[mobile],[fax], [email], [companyName],
[licence],[brn], [vat], [companyStreet], [companyCity], [status]
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY id ASC) AS rownumber,
[id], [firstname], [lastname], [street], [city],
[phone], [mobile], [fax], [email], [companyName],
[licence], [brn], [vat], [companyStreet], [companyCity], [status]
FROM
@registerDetails) AS foo
WHERE
rownumber = @I
-- this stored procedure handles the saving of the current customer row just defined above
-- if there is any error from that sproc, it will jump to CATCH block
--save the error message in the temp table and continue
--with the next customer row in the while loop.
exec dbo.sp_SaveCustomer @customerRow
END TRY
BEGIN CATCH
IF @@TranCount = 0
-- Transaction started in procedure.
-- Roll back complete transaction.
ROLLBACK TRANSACTION;
if XACT_STATE()= -1 rollback transaction
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE() + ' ' + (select firstname from @registerDetails where id=@I)
SELECT @ErrorSeverity = ERROR_SEVERITY();
SELECT @ErrorState = ERROR_STATE()
INSERT INTO #registrationResults (error,id)
SELECT @ErrorMessage, @I
END CATCH
set @I = @I +1
end
COMMIT TRANSACTION registerTran
select * from #registrationResults
其中,registrationErrors
和clientDetailsDT
是强类型数据表
这一条没有:
begin catch
IF @@TranCount > 0 or XACT_STATE()= -1 ROLLBACK TRANSACTION;
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
DECLARE @ErrorLine INT;
SELECT @ErrorMessage = ERROR_MESSAGE();
SELECT @ErrorSeverity = ERROR_SEVERITY();
SELECT @ErrorState = ERROR_STATE();
SELECT @ErrorLine = ERROR_Line();
****ERROR -- THIS SELECT WAS MESSING ALL UP as it was this select that was being returned to the .NET and not the select of the desired #temp table after, hence returning 0 resultset as this select was EMPTY. !!
select status_indicator from InsertInvoiceTriggerData where session_GUID = guid**
delete from InsertInvoiceTriggerData where session_GUID = @guid**
INSERT INTO #registrationResults (error,id)
SELECT @ErrorMessage, NULL
select * from #registrationResults
end catch
有没有关于如何返回结果集的建议?我没有看到您的数据库代码,但根据我的经验,
catch
捕获的第一个错误意味着整个事务必须回滚。除此之外,它还意味着在任何给定的情况下,我都不会返回超过1个错误
因此,我在存储过程中使用了2个标量输出参数,即:
@Error int = null output,
@Message nvarchar(2048) = null output
我可以像检索任何其他输出变量一样检索它们
UPD:即使您添加了一些代码,我仍然无法准确理解您的问题所在。但是,我发现您的代码有几个问题,所以我将指出它们,其中一个可能会解决问题。我只评论第一个片段,因为最后一个片段太不完整了
- 您应该在循环之前的某个位置启动最外层的事务。否则,代码将失败
- 如果我猜对了,您在
存储过程中实现了所有保存点逻辑。如果没有,整个讨论就毫无意义,因为在您显示的代码中没有dbo.sp\u SaveCustomer
或save-tran
语句rollback@savepoint
- 第一个
语句-catch
IF@@tracount=0回滚事务
都是错误的。如果条件成功,将导致尝试回滚不存在的事务时出错。如果您依赖保存点,则不应出现在此处
- 它后面的下一个应该导致无条件中断:
如果XACT_STATE()=-1开始 回滚事务; 打破 结束代码>
- 捕获代码的其余部分可以替换为:
插入@registrationResults(错误,id) 选择error_message()+“”+firstname,id 来自@registerDetails,其中id=@I代码>
- 此外,千万不要为此使用临时表,因为回滚也会影响临时表。为此,请始终使用表变量,它们是非事务性的(与任何其他变量一样)
应该是有条件的,因为此时您可能没有要提交的事务:commit
如果@trancount>0,则提交传输代码>
- 在
语句中指定保存点名称没有意义,它只会导致混淆(尽管不被视为错误)。此外,此模块中不应该有任何保存点(除非您在循环之前定义了它)commit
dbo.SaveCustomer
存储过程中实际发生了什么
UPD2:以下是我用来从存储过程接收记录集的VB.NET代码示例:
Private Function SearchObjectsBase( _
SearchMode As penum_SEARCH_MODE, SearchCriteria As String
) As DataSet
Dim Cmd As DbCommand, Pr As DbParameter, dda As DbDataAdapter
' Initialise returning dataset object
SearchObjectsBase = New DataSet()
Cmd = MyBase.CreateCommand(String.Format("dbo.{0}", SearchMode))
With Cmd
' Parameter definitions
Pr = .CreateParameter()
With Pr
.ParameterName = "@SearchCriteria"
.DbType = DbType.Xml
.Value = SearchCriteria
End With
.Parameters.Add(Pr)
' Create data adapter to use its Fill() method
dda = DbProviderFactories.GetFactory(.Connection).CreateDataAdapter()
' Assign the prepared DbCommand as a select method for the adapter
dda.SelectCommand = Cmd
' A single resultset is expected here
dda.Fill(SearchObjectsBase)
End With
' Set error vars and get rid of it
Call MyBase.SetErrorOutput(Cmd)
' Check for errors and, if any, discard the dataset
If MyBase.ErrorNumber <> 0 Then SearchObjectsBase.Clear()
End Function
这里,SearchPatients()是SearchObjectsBase()之上的包装器。标量参数可以很好地处理您提到的单个输出,但在我的例子中,我有一个事务在while循环中进行,每次事务没有成功,它都会回滚到保存点,并如上所述将错误消息保存在临时表中。循环完成后,返回结果集fine。但是如果您想从CATCH块返回temp表中提到的参数,您将如何实现它?那么,您可以将错误结果集转换为XML,并通过XML输出参数返回它。因为,即使到2014年,表变量参数仍然是只读的。请再次查看原始帖子,我已经包含了数据库代码。另外,根据MSDN文档,这在存储过程之间起作用,但是我们如何从.NET读取游标呢?恐怕我不能理解你的问题。你有正确的代码和错误的代码;为什么要用错的呢?它将为每个错误生成一个单独的记录集,每个错误中只有一行。为什么不能使用正确的游标?而且,就为了记录,返回游标的参数的数据类型被称为
cursor
。但我一点也不知道如何在客户端处理它,假设这是可能的。
Private Function SearchObjectsBase( _
SearchMode As penum_SEARCH_MODE, SearchCriteria As String
) As DataSet
Dim Cmd As DbCommand, Pr As DbParameter, dda As DbDataAdapter
' Initialise returning dataset object
SearchObjectsBase = New DataSet()
Cmd = MyBase.CreateCommand(String.Format("dbo.{0}", SearchMode))
With Cmd
' Parameter definitions
Pr = .CreateParameter()
With Pr
.ParameterName = "@SearchCriteria"
.DbType = DbType.Xml
.Value = SearchCriteria
End With
.Parameters.Add(Pr)
' Create data adapter to use its Fill() method
dda = DbProviderFactories.GetFactory(.Connection).CreateDataAdapter()
' Assign the prepared DbCommand as a select method for the adapter
dda.SelectCommand = Cmd
' A single resultset is expected here
dda.Fill(SearchObjectsBase)
End With
' Set error vars and get rid of it
Call MyBase.SetErrorOutput(Cmd)
' Check for errors and, if any, discard the dataset
If MyBase.ErrorNumber <> 0 Then SearchObjectsBase.Clear()
End Function
Dim XDoc As New XElement("Criteria"), DS As DataSet = Nothing, DT As DataTable
...
DS = .SearchPatients(XDoc.ToString(SaveOptions.None))
' Assign datasource to a grid
Me.dgr_Search.DataSource = DS.Tables.Item(0)