If passing a DataSet to a web method for update using ADO.NET and the
update fails, the parameter list may get corrupt.
The following code example consists of a Web Service and a consumer
console application, both written in C# using VS.NET.
A tiny MSSQL database is required to run the example:
create table test1 (id numeric(1) unique)
The console app creates a DataSet and passes it to the Web Service for
update. The first execution is OK but subsequent executions will
correctly cause a UNIQUE constrain violation. The err parameter gets
set to 1 BUT UPON RETURN TO THE CALLER IT HAS THE VALUE 0.
I am aware that removing the "ref" attribute on the DataSet parameter
will solve the problem in this case but still, it seems like a bug to
me.
Console Application:
====================
using System;
using System.Data;
using System.Diagnostics;
namespace BugReportConsumer
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
localhost.Service1 service = new
BugReportConsumer.localhost.Service1();
int err;
string msg;
DataSet ds = new DataSet();
DataTable t = ds.Tables.Add("test1");
t.Columns.Add("id",System.Type.GetType("System.Int 32"));
object[] row = {1};
t.Rows.Add(row);
service.UpdateData(ref ds, out err, out msg);
Trace.WriteLine("Return: "+err.ToString() + " Msg: " + msg);
}
}
}
Web Service:
============
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
namespace BugReport
{
public class Service1 : System.Web.Services.WebService
{
public Service1()
{
//CODEGEN: This call is required by the ASP.NET Web Services
Designer
InitializeComponent();
}
#region Component Designer generated code
//Required by the Web Services Designer
private IContainer components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if(disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
[WebMethod]
public int UpdateData(ref DataSet ds, out int err, out string
errMsg)
{
int nRows = 0;
err = 0;
errMsg = "";
try
{
SqlConnection conn = new SqlConnection("server=localhost" +
";database=testdb" +
";user id=sa" +
";password=secret");
string stmt = "SELECT * FROM test1";
SqlDataAdapter da = new SqlDataAdapter(stmt, conn);
SqlCommandBuilder cmd = new SqlCommandBuilder(da);
nRows = da.Update(ds,"test1");
}
catch (Exception e)
{
err = 1;
errMsg = e.Message;
return 0;
}
return nRows;
}
}
}