INF: Handling SQL Server Error Messages When a Stored Procedure is Used in the SqlDataAdapter UpdateCommand Method (811482)
The information in this article applies to:
- Microsoft SQL Server 2000 (all editions)
- Microsoft ADO.NET (included with the .NET Framework 1.1)
SUMMARYWhen the UpdateCommand method of the SqlDataAdapter object uses a SQL Server stored procedure that raises an
error after it returns a result set, the ADO.NET client application may
not trap the error raised by SQL Server. However, you can use the SqlDataReader object to trap such error messages. This article describes how to
use the SqlDatareader object to trap the error raised by the stored procedure.
MORE INFORMATIONThe SqlDataAdapter object serves as a bridge between a DataSet object and a SQL
Server database. SqlDataAdapter is an intermediary object that populates a DataSet object
with data that is retrieved from a SQL Server database. By using the UpdateCommand method of SqlDataAdapter, you can update the database to reflect the changes (such as
inserts, updates, and deletes) made to the DataSet object. You can use a
Transact-SQL command or a stored procedure in the UpdateCommandmethod. If a stored procedure is used in the UpdateCommand method of SqlDataAdapter, the client may not receive the error messages that are
raised by the stored procedure after the result set is returned.
Note: Manipulating the SET NOCOUNT or the severity level of the
RAISERROR message in the stored procedure does not change this behavior.
You can use SqlDataReader as an alternative solution to this problem. The SqlDataReaderprovides more flexibility in handling store procedures that
return multiple result sets. The sample code, in the section that follows,
demonstrates how to use SqlDataReader to update a data source and trap the error message that is raised
by the stored procedure. Create a Sample SQL Server Table and Stored ProcedureTo create a SQL Server table and stored procedure that
you can use in the Visual C# .NET code samples, follow these steps:
- Open SQL Query Analyzer, and then connect to the database
where you want to create the sample table. The code samples in this article use
the Northwind database that is included with Microsoft SQL Server.
- To create a sample table that is named CustTest, and to insert a record into the table, run the following
Transact-SQL statements:
Create Table CustTest
(
CustID int primary key,
CustName varchar(20)
)
Insert into CustTest values (1,'John')
Insert into CustTest values (2,'Joe')
- Create a stored procedure named updateCustTest. You can use this stored procdure to reflect the modified rows in
the DataSet back to the source database. The updateCustTest stored procedure returns a recordset, updates the database and
raises an error by using RAISERROR. To create the updateCustTest stored procedure, run the following Transact-SQL statements:
Create procedure updateCustTest(@Custid varchar(20), @custName varchar(20))as
Begin
select custid, custName from custTest where custid= @custid
update custTest set custName = @custName
where custId = @custid
RAISERROR('Test error raised by Raiserror',16,1)
End
Visual C# .NET Client ApplicationThis section describes the steps to follow to reproduce
the behavior and the steps to follow to resolve the behavior.
- To create a new Visual C# .NET console application, follow
these steps:
- Start Microsoft Visual Studio .NET.
- On the File menu, point to
New, and then click Project.
- Click Visual C# Project under
Project Types, and then click Console
Application under Templates.
- Replace the default contents of Class1 with the following
code:
using System;
using System.Data;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using System.Data.Common;
namespace SQLDataAdapterConsole
{
class Class1
{
public static void Main()
{
SqlConnection cn = new SqlConnection();
SqlDataAdapter sqlDa;
//Set the connection string of the SqlConnection object to connect
//to the SQL Server database where you created the sample table.
cn.ConnectionString = "Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=northwind;Data Source=ServerName";
cn.Open();
//Initialize the SqlDataAdapter object by specifying a Select command
//that retrieves data from the sample table.
sqlDa = new SqlDataAdapter("select * from custTest", cn);
//This function uses Uptade method of DataAdapter to update the modified DataSet data in the source database
//Notice that the error raised by the Update Command Stored Procedure cannot be trapped
UpdateUsingDataAdapter(sqlDa);
//This function uses DataReader to update the modified data in the source database
//Notice that the error raised by the Update Command Stored Procedure can be trapped
UpdateUsingDataReader(sqlDa);
cn.Close();
Console.ReadLine();
}
// This function uses Update method of SqlDataAdapter for Updating the data
public static void UpdateUsingDataAdapter(SqlDataAdapter da)
{
Console.WriteLine("Updating Database using Update Command of SqlDataAdapter");
SqlCommand updateCmd;
DataSet CustomersDataSet = new DataSet();
//Create update command for SqlDataAdapter
updateCmd = new SqlCommand("exec updateCustTest @pCustId, @pCustName", da.SelectCommand.Connection);
//Add parameters for the stored procedure
updateCmd.Parameters.Add(new SqlParameter("@pCustName", SqlDbType.VarChar));
updateCmd.Parameters["@pCustName"].SourceVersion = DataRowVersion.Current;
updateCmd.Parameters["@pCustName"].SourceColumn = "CustName";
updateCmd.Parameters.Add(new SqlParameter("@pCustId", SqlDbType.VarChar));
updateCmd.Parameters["@pCustId"].SourceVersion = DataRowVersion.Original;
updateCmd.Parameters["@pCustId"].SourceColumn = "CustId";
//Initialize the UpdateCommand of SqlDataAdapter
da.UpdateCommand = updateCmd;
//Populate the DataSet by running the Fill method of the SqlDataAdapter.
da.Fill(CustomersDataSet,"custTest");
//Write out the value in the CustName field before updating the data using the DataSet.
Console.WriteLine("Customer Name before Update : " + CustomersDataSet.Tables["CustTest"].Rows[0]["CustName"]);
//Modify the value of the CustName field.
CustomersDataSet.Tables["CustTest"].Rows[0]["CustName"] = "Bill";
// Get the dataSet that is modified.
DataSet modifiedDS = CustomersDataSet.GetChanges(DataRowState.Modified);
try
{
da.Update(modifiedDS,"CustTest");
Console.WriteLine("Customer name is updated to 'Bill'.");
Console.WriteLine("The Stored Procedure error is not trapped.");
}
catch
{
Console.WriteLine("Stored Procedure error trapped.");
}
}
//This function uses DataReader for updating the
public static void UpdateUsingDataReader(SqlDataAdapter da)
{
Console.WriteLine("\n\nUpdating Database using DataReader to trap the Stored Procedure error.");
DataSet CustomersDataSet = new DataSet();
SqlDataReader mySqlDataReader;
//Populate the DataSet by running the Fill method of the SqlDataAdapter.
da.Fill(CustomersDataSet,"custTest");
//Modify the value of the CustName field.
CustomersDataSet.Tables["CustTest"].Rows[0]["CustName"] = "Michel";
// Get the dataSet that is modified.
DataSet modifiedDS = CustomersDataSet.GetChanges(DataRowState.Modified);
SqlCommand updateCmd;
foreach (DataRow dr in modifiedDS.Tables[0].Rows)
{
// Set the update command for modified data in the DataSet.
updateCmd = new SqlCommand("updateCustTest '" + dr[0] +"', '" + dr[1] + "'", da.SelectCommand.Connection);
try
{
// Execute the update command.
mySqlDataReader = updateCmd.ExecuteReader();
while(!mySqlDataReader.IsClosed)
{
while (mySqlDataReader.Read())
{
Console.WriteLine("Customer name returned by the procedure :" + mySqlDataReader.GetValue(1));
}
// Get the results set returned by the update command.
mySqlDataReader.NextResult();
Console.WriteLine("\n");
}
mySqlDataReader.Close();
Console.WriteLine("Customer Name updated successfully");
}
catch(SqlException e)
{
// Get the error collection and write the error on the console.
Console.WriteLine("Error Number is : " + e.Number);
Console.WriteLine("Error Message is : " + e.Message);
}
}
}
}
}
- Modify the connection string as appropriate for your
environment.
- Save, and then run the application. Watch the message as
the program executes.
- Press any key to dismiss the console window and stop the
application.
REFERENCES For
additional information, click the following article number to view the article
in the Microsoft Knowledge Base: 313483
INFO: Roadmap for ADO.NET DataAdapter Objects
Modification Type: | Major | Last Reviewed: | 5/8/2003 |
---|
Keywords: | kbTSQL kbtable kbSystemData kbStoredProc kbSqlClient kbDatabase kbDataAdapter kbinfo KB811482 kbAudDeveloper |
---|
|