【发布时间】:2015-08-22 09:53:58
【问题描述】:
我有一个存储过程,它可以返回 PRINT 消息和来自 SELECT 语句的常规查询结果。使用this thread 中提供的优雅解决方案,我可以在我的C# 代码中调用SqlCommand.ExecuteNonQuery() 时轻松捕获我的PRINT 消息。问题是,我也想返回我的结果集。
当我使用SqlDataReader 使用SqlCommand.ExecuteReader 从我的存储过程中取回查询结果时,捕获我的PRINT 消息的事件处理程序永远不会像我使用SqlCommand.ExecuteNonquery 时那样触发。
开始似乎我只能拥有一个或另一个。有没有办法让我同时捕获我的PRINT 消息和我的查询结果?
这是我的 SQL 存储过程的 sn-p:
IF EXISTS
(
SELECT MFG_PART_NUMBER, COUNT(*) AS RecordCount
FROM [PartsManagement].[ManufacturerCatalogPart]
WHERE CatalogID = @CatalogID
GROUP BY MFG_PART_NUMBER
HAVING COUNT(*) > 1
)
BEGIN
SELECT MFG_PART_NUMBER, COUNT(*) AS RecordCount
FROM [PartsManagement].[ManufacturerCatalogPart]
WHERE CatalogID = @CatalogID
GROUP BY MFG_PART_NUMBER
HAVING COUNT(*) > 1;
PRINT 'The update was not executed because duplicate MFG_PART_NUMBERs were found in the catalog. Delete the duplicates and try again.';
END;
这是我的代码中的一个 sn-p:
//field
private string sqlPrintMessage = "";
//event handler for sql PRINT message
void myConnection_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
sqlPrintMessage = e.Message;
}
public void SomeMethod()
{
using (SqlConnection sqlcon = new SqlConnection(ConnectionManager.GetConnectionString()))
{
sqlcon.InfoMessage += new SqlInfoMessageEventHandler(myConnection_InfoMessage);
SqlCommand sqlcmd = new SqlCommand("[ManufacturerCatalogUpdate].[CheckCatalogForDuplicates]", sqlcon);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("@CatalogID", catalogID);
sqlcon.Open();
//SqlDataReader reader = sqlcmd.ExecuteReader();
sqlcmd.ExecuteNonQuery();
if (sqlPrintMessage == "") //then proceed with update
{
//do some logic
}
else
{
//System.Diagnostics.Debug.WriteLine(sqlPrintMessage);
//List<DuplicatePartCount> duplicateParts = new List<DuplicatePartCount>();
//while (reader.Read())
//{
// DuplicatePartCount record = new DuplicatePartCount();
// record.MFG_PART_NUMBER = reader.GetString(0);
// record.count = reader.GetInt32(1);
// duplicateParts.Add(record);
//}
}
}
}
【问题讨论】:
-
为连接 InfoMessage 事件添加一个处理程序,以获取由
PRINT和RAISERROR生成的信息和警告消息(严重性为 10 或更低)。 -
@DanGuzman,我已经在这样做了(请参阅我的第二个代码块)。问题是,当我使用
ExecuteReader时,该事件永远不会被触发。 -
Jacob,这里发生了其他事情。我确实看到了事件处理程序,但我可以向您保证,这应该可以工作,因为我已经多次这样做了。当然,这可能是时间问题。我知道,例如,在您关闭阅读器之前,输出参数值不可用。稍后我会看一下并与我的工作进行比较。如果之前没有其他人有答案,那么我会尝试找到问题。
-
您需要在 InfoMessage 事件处理程序触发之前导航到阅读器结果的末尾。在底层的 TDS 流协议中,InfoMessage 位于 select 语句的上述结果后面,并且在被消费之前不可用。
-
Jacob:不,这与 DataTables 和/或 DataAdapter 无关。如果有的话,使用带有
Fill方法的 DataTable 的人可能会更快地收到消息,但这只是因为 fill 方法在继续执行下一行代码之前完全通过阅读器。最后,您不需要我在回答中显示的消息。你只需要reader.HasRows()。
标签: c# sql-server stored-procedures resultset