SqlPipe object
Applies to: SQL Server
In previous versions of SQL Server, it was common to write a stored procedure (or an extended stored procedure) that sent results or output parameters to the calling client.
In a Transact-SQL stored procedure, any SELECT
statement that returns zero or more rows sends the results to the connected caller's "pipe."
For common language runtime (CLR) database objects running in SQL Server, you can send results to the connected pipe using the Send
methods of the SqlPipe
object. Access the Pipe
property of the SqlContext
object to obtain the SqlPipe
object. The SqlPipe
class is conceptually similar to the Response
class found in ASP.NET.
For more information, see Microsoft.SqlServer.Server.SqlPipe.
Return tabular results and messages
The SqlPipe
object has a Send
method, which has three overloads. They are:
void Send(string message)
void Send(SqlDataReader reader)
void Send(SqlDataRecord record)
The Send
method sends data straight to the client or caller. It's usually the client that consumes the output from the SqlPipe
, but with nested CLR stored procedures, the output consumer can also be a stored procedure. For example, Procedure1
calls SqlCommand.ExecuteReader()
with the command text EXEC Procedure2
. Procedure2
is also a managed stored procedure. If Procedure2
now calls SqlPipe.Send(SqlDataRecord)
, the row is sent to the reader in Procedure1
, not the client.
The Send
method sends a string message that appears on the client as an information message, equivalent to PRINT
in Transact-SQL. It can also send a single-row result-set using SqlDataRecord
, or a multi-row result-set using a SqlDataReader
.
The SqlPipe
object also has an ExecuteAndSend
method. This method can be used to execute a command (passed as a SqlCommand
object) and send results directly back to the caller. If there are errors in the command that was submitted, exceptions are sent to the pipe, and a copy is sent to calling managed code. If the calling code doesn't catch the exception, it propagates up the stack to the Transact-SQL code and appears in the output twice. If the calling code does catch the exception, the pipe consumer still sees the error, but there isn't a duplicate error.
It can only take a SqlCommand
that is associated with the context connection; it can't take a command that is associated with the non-context connection.
Return custom result sets
Managed stored procedures can send result sets that don't come from a SqlDataReader
. The SendResultsStart
method, along with SendResultsRow
and SendResultsEnd
, allows stored procedures to send custom result sets to the client.
SendResultsStart
takes a SqlDataRecord
as an input. It marks the beginning of a result set and uses the record metadata to construct the metadata that describes the result set. It doesn't send the value of the record with SendResultsStart
. All the subsequent rows, sent using SendResultsRow
, must match that metadata definition.
After you call the SendResultsStart
method, only SendResultsRow
and SendResultsEnd
can be called. Calling any other method in the same instance of SqlPipe
causes an InvalidOperationException
. SendResultsEnd
sets SqlPipe
back to the initial state in which other methods can be called.
Example
The uspGetProductLine
stored procedure returns the name, product number, color, and list price of all products within a specified product line. This stored procedure accepts exact matches for prodLine
.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void uspGetProductLine(SqlString prodLine)
{
// Connect through the context connection.
using (SqlConnection connection = new SqlConnection("context connection=true"))
{
connection.Open();
SqlCommand command = new SqlCommand(
"SELECT Name, ProductNumber, Color, ListPrice " +
"FROM Production.Product " +
"WHERE ProductLine = @prodLine;", connection);
command.Parameters.AddWithValue("@prodLine", prodLine);
try
{
// Execute the command and send the results to the caller.
SqlContext.Pipe.ExecuteAndSend(command);
}
catch (System.Data.SqlClient.SqlException ex)
{
// An error occurred executing the SQL command.
}
}
}
};
The following Transact-SQL statement executes the uspGetProduct
procedure, which returns a list of touring bike products.
EXECUTE uspGetProductLineVB 'T';