我有一个不需要任何参数的存储过程,并返回值0和消息:
(94 row(s) affected)
(1 row(s) affected)
我的问题是如何获取消息:
(94 row(s) affected)
(1 row(s) affected)
这是我调用存储过程的.NET方法:
public List<MessageClass> ChequesToUpdate()
{
message = new List<MessageClass>();
MessageClass item = new MessageClass();
try
{
using (connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("MyStoredProcedure", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.ExecuteNonQuery();
item.message = "message";
}
}
}
catch (Exception e)
{
item.message = e.Message;
}
finally
{
connection.Close();
}
message.Add(item);
return message;
}
我希望将信息放在item.message
中,我该如何做到这一点?
答案 0 :(得分:3)
在您的存储过程中,您可以查询@@ROWCOUNT,它会为您提供受影响的记录。现在,您可以使用SET
或SELECT
语句(例如
SET MyRecordCount = @@RowCount
或
SELECT MyRecordCount = @@RowCount
或者,如果您在一个程序中有多个操作,则需要跟踪您可以创建多个变量并多次调用SET
或SELECT
或使用TABLE
变量,例如
DECLARE @recordCount table (Records int not null)
--RUN PROCEDURE CODE
INSERT INTO @recordCount VALUES (@@ROWCOUNT)
--RUN MORE PROCEDURECT CODE
INSERT INTO @recordCount VALUES (@@ROWCOUNT)
--RETURN THE Row Count
SELECT Records FROM @recordCount
这会将@@ROWCOUNT
的值插入表变量@recordCount
接下来要获取此信息,您需要从@recordCount
表中选择最后一行。
最后在您的代码中使用数据读取器而不是ExecuteNonQuery()
方法。
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("MyStoredProcedure", connection))
{
command.CommandType = CommandType.StoredProcedure;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
item.message = reader.GetString(0);
}
reader.Close();
}
}
}
现在消息实际上是受影响的行的整数而不是术语(98) row affected
但是如果你真的想要那个确切的消息可以按照你的意愿格式化字符串。
item.message = string.Format("({0}) rows affected", reader.GetInt32(0))
答案 1 :(得分:3)
ExecuteNonQuery
返回受影响行的总数。因此,如果您只想要行的总数,那么您只需使用以下语句即可获得它:
var x = command.ExecuteNonQuery();
否则,您必须在存储过程中使用用户定义RAISERROR
消息并从C#connection.InfoMessage
事件中捕获它。我已经设置了测试环境并对其进行了测试。我创建了一个表并插入了一些数据来检查我的SQL&amp; C#代码。请查看下面的SQL&amp; C#代码。
SQL:
Create Table psl_table
(
[values] NVarChar(MAX)
)
Insert Into psl_table Values('a')
Insert Into psl_table Values('a')
Insert Into psl_table Values('a')
Insert Into psl_table Values('b')
Insert Into psl_table Values('b')
Insert Into psl_table Values('b')
Insert Into psl_table Values('b')
Insert Into psl_table Values('b')
Insert Into psl_table Values('b')
Insert Into psl_table Values('b')
Create Proc MyStoredProcedure
As
Begin
-- Declare a variable for Message
Declare @Msg NVarChar(MAX)
-- 1st SQL Statement
Update psl_table Set [Values]='a' Where [Values]!='a'
-- Generate the message and print that can get from C#
Set @Msg = '(' + Convert(NVarChar,@@RowCount) + ' row(s) affected)'
RAISERROR( @Msg, 0, 1 ) WITH NOWAIT
-- 2nd SQL Statement
Update psl_table Set [Values]='a'
-- Generate the message and print that can get from C#
Set @Msg = '(' + Convert(NVarChar,@@RowCount) + ' row(s) affected)'
RAISERROR( @Msg, 0, 1 ) WITH NOWAIT
End
在这个SQL中,我已经声明了一个变量 @Msg 来存储消息和内置函数 RAISERROR 来抛出消息。
C#CODE:
public List<MessageClass> ChequesToUpdate()
{
message = new List<MessageClass>();
MessageClass item = new MessageClass();
try
{
using (connection = new SqlConnection(connectionString))
{
connection.Open();
connection.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
{
item.message = e.Message;
};
using (SqlCommand command = new SqlCommand("MyStoredProcedure", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.ExecuteNonQuery();
}
}
}
catch (Exception e)
{
item.message = e.Message;
}
finally
{
connection.Close();
}
message.Add(item);
return message;
}
我已经修改了所需输出的代码。我使用 connection.InfoMessage 事件来捕获从SQL抛出的消息。
出于测试目的,我在Console中打印输出。
输出:
答案 2 :(得分:0)
存储过程中语句的每一端,在表中插入@@rowcount
。然后使用数据集将其提取回Method。
答案 3 :(得分:0)
默认情况下,您无法在C#
中获取受行影响的消息。相反,您需要将您的过程修改为PRINT/RAISERROR
消息,这样您就可以使用@Julian提到的SqlConnection.InfoMessage
在C#中访问它们。
答案 4 :(得分:0)
我会从程序返回@@ rowcount,在.net代码中我会读取该值。
在您的程序中添加return(@@ rowcount),如下所示
create procedure testprocedure
as
begin
update test1 set id =100
return(@@rowcount)
end
您的.net代码在参数方向
下面显示如下 SqlConnection conn;
using(conn = new SqlConnection(@"Data Source=;Initial Catalog=;User ID = sa;Password="))
{
conn.Open();
using (SqlCommand command = new SqlCommand("testprocedure", conn))
{
command.CommandType = CommandType.StoredProcedure;
SqlParameter retValue = command.Parameters.Add("return", SqlDbType.Int);
retValue.Direction = ParameterDirection.ReturnValue;
command.ExecuteNonQuery();
Console.WriteLine("no of records affected " + retValue.Value);
Console.ReadLine();
}
}
答案 5 :(得分:0)
您无法捕获这些特定消息(即(94 row(s) affected)
),因为它们不是由SQL Server发送的;它们由客户端程序发送,SQLCMD或SSMS。但是,是的,您可以捕获行计数,而无需向存储过程添加RAISERROR
或PRINT
语句。此外,您(或许多其他人阅读此问题)甚至可能无法更新存储过程以注入输出的额外PRINT
/ RAISERROR
/ SELECT
语句行数。
但首先,关于其他一些建议的两个警告:
您可能无法使用ExecuteNonQuery
的返回值,因为它不会返回非DML语句的值,包括SELECT
语句。它只返回INSERT
,UPDATE
和DELETE
语句中的值,如SqlCommand.ExecuteNonQuery所述:
对于UPDATE,INSERT和DELETE语句,返回值是受命令影响的行数。 ...对于所有其他类型的语句,返回值为-1。
问题并未说明正在执行哪些类型的查询,因此您可能只使用这些DML语句。但是,每个人都应该知道这个返回值反映了什么(而不是)。
您可能不希望通过InfoMessage
处理程序捕获打印消息,因为这需要解析以确保捕获的消息不是其他消息,例如警告或其他信息。
话虽这么说,你想设置一个SqlCommand.StatementCompleted事件处理程序,因为它传递了每个语句受影响的行(RecordCount
是int
)。
internal static void StatementCompletedHandler(object Sender,
StatementCompletedEventArgs EventInfo)
{
// do something with EventInfo.RecordCount
return;
}
然后将其附加到SqlCommand
对象:
_Command.StatementCompleted += StatementCompletedHandler;
如果在ASP.NET中工作限制了将返回值存储在静态变量中的能力(因为它是共享的并且可能不是线程安全的),那么您可以将处理程序内联定义为匿名委托,在这种情况下它能够访问在ChequesToUpdate
方法中声明的实例变量。