The previous post demonstrated how to load JSON into SQL Server using a stored procedure and C#. This post will examine the opposite - how to retrieve JSON data from SQL Server using a stored procedure and C#. Just like with the JSON loading technique, the new JSON functions in SQL Server 2016 allow for this retrieval technique.
Here’s how it works in short:
Data stored in a database table will be converted to JSON text in the stored procedure and returned to the C# client via an output parameter.
SQL Server Table
Let’s start with the SQL Server table, which will contain one row of sample performance counter data.
--Create table
DROP TABLE IF EXISTS dbo.PerfCounter
CREATE TABLE dbo.PerfCounter(
RecordedDateTime datetime2(0) NOT NULL,
RecordedDateTimeLocal datetime2(0) NOT NULL,
CpuPctProcessorTime smallint NOT NULL,
MemAvailGbytes smallint NOT NULL
)
--Insert sample row
INSERT INTO [dbo].[PerfCounter]
([RecordedDateTime]
,[RecordedDateTimeLocal]
,[CpuPctProcessorTime]
,[MemAvailGbytes])
VALUES
('2018-03-19 15:15:40'
,'2018-03-19 11:15:40'
,12
,28)
Before looking at the stored procedure, let’s test the query that will be used in the procedure to make sure it’s returning the results in the desired format. For this example, we’ll pretend that there are multiple rows in the table, and we’ll return only the most recent row.
-- Retreive most recent row
SELECT TOP(1)
[RecordedDateTime] AS 'dateTime'
,[RecordedDateTimeLocal] AS 'dateTimeLocal'
,[CpuPctProcessorTime]
,[MemAvailGbytes]
FROM [dbo].[PerfCounter]
ORDER BY RecordedDateTimeLocal DESC
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
The FOR JSON clause will convert the query results to JSON text, which should look like what is shown below when formatted nicely. Notice that the aliases in the SQL query are used in the outputted JSON. There are other formatting options available with FOR JSON. This is a simple example.
{
"dateTime": "2018-03-19T15:15:40",
"dateTimeLocal": "2018-03-19T11:15:40",
"CpuPctProcessorTime": 12,
"MemAvailGbytes": 28
}
Now that the query is working correctly, let’s create the stored procedure. The same query tested above is used in the procedure, and the results are assigned to an output parameter.
DROP PROCEDURE IF EXISTS dbo.RetrievePerfCounterData
GO
CREATE PROCEDURE dbo.RetrievePerfCounterData
@jsonOutput NVARCHAR(MAX) OUTPUT
AS
BEGIN
SET @jsonOutput = (SELECT TOP (1)
RecordedDateTime AS 'dateTime'
,RecordedDateTimeLocal AS 'dateTimeLocal'
,CpuPctProcessorTime
,MemAvailGbytes
FROM dbo.PerfCounter
ORDER BY RecordedDateTimeLocal DESC
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
END
Let’s test the procedure in SQL Server Management Studio to make sure that it’s working:
DECLARE @json AS NVARCHAR(MAX)
EXEC dbo.RetrievePerfCounterData @jsonOutput = @json OUTPUT
SELECT @json
The JSON text should be returned to the results grid:
C# Code
With the table and stored procedure in place, let’s look at the code. As per usual, I use LINQPad for these examples. The following namespace is required:
System.Data.SqlClient
The script is below. Be sure to update the connection string on line 3 for your SQL Server instance and database.
static void Main()
{
string connString = @"Data Source=localhost\sql2016;Initial Catalog=dwDev;Integrated Security=SSPI";
string sprocname = "RetrievePerfCounterData";
string jsonOutputParam = "@jsonOutput";
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sprocname, conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
// Create output parameter. "-1" is used for nvarchar(max)
cmd.Parameters.Add(jsonOutputParam, SqlDbType.NVarChar, -1).Direction = ParameterDirection.Output;
// Execute the command
cmd.ExecuteNonQuery();
// Get the values
string json = cmd.Parameters[jsonOutputParam].Value.ToString();
Console.WriteLine(json);
}
}
}
When you run the C# script, the JSON string should returned from the stored procedure and written to the console. When nicely formatted it should look like this:
{
"dateTime": "2018-03-19T15:15:40",
"dateTimeLocal": "2018-03-19T11:15:40",
"CpuPctProcessorTime": 12,
"MemAvailGbytes": 28
}
With the JSON data now in the application, it can be transmitted to another location or deserialized for use within the application.
Other Considerations
NVARCHAR(MAX) is required by the SQL Server functions that handle JSON text. Since the JSON text is simply being output in this example, you can use other string types besides NVARCHAR(MAX) with this technique.