tags:

views:

92

answers:

2

Hi, I need advice. I have asp.net web service and winforms client app. Client call this web method and get dataset.

   1. [WebMethod]  
   2.  public DataSet GetSecureDataSet(string id)  
   3.  {  
   4.   
   5.   
   6.      SqlConnection conn = null;  
   7.      SqlDataAdapter da = null;  
   8.      DataSet ds;  
   9.      try  
  10.      {  
  11.   
  12.          string sql = "SELECT * FROM Tab1";  
  13.   
  14.          string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;  
  15.   
  16.          conn = new SqlConnection(connStr);  
  17.          conn.Open();  
  18.   
  19.          da = new SqlDataAdapter(sql, conn);  
  20.   
  21.          ds = new DataSet();  
  22.          da.Fill(ds, "Tab1");  
  23.   
  24.          return ds;  
  25.      }  
  26.      catch (Exception ex)  
  27.      {  
  28.          throw ex;  
  29.      }  
  30.      finally  
  31.      {  
  32.          if (conn != null)  
  33.              conn.Close();  
  34.          if (da != null)  
  35.              da.Dispose();  
  36.      }  
  37.  }  

After he finish work he call this update web method. He can add, delete and edit rows in table in dataset.

  [WebMethod]
    public bool SecureUpdateDataSet(DataSet ds)
    {

        SqlConnection conn = null;
        SqlDataAdapter da = null;
        SqlCommand cmd = null;
        try
        {

            DataTable delRows = ds.Tables[0].GetChanges(DataRowState.Deleted);

            DataTable addRows = ds.Tables[0].GetChanges(DataRowState.Added);

            DataTable editRows = ds.Tables[0].GetChanges(DataRowState.Modified);

            string sql = "UPDATE * FROM Tab1";

            string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;

            conn = new SqlConnection(connStr);
            conn.Open();

            cmd = new SqlCommand(sql, conn);
            da = new SqlDataAdapter(sql, conn);

            if (addRows != null)
            {
                da.Update(addRows);
            }

            if (delRows != null)
            {
                da.Update(delRows);
            }

            if (editRows != null)
            {
                da.Update(editRows);
            }


            return true;

        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            if (conn != null)
                conn.Close();
            if (da != null)
                da.Dispose();
        }
    }

Code on client side

   1. //on client side is dataset bind to datagridview   
   2. Dataset ds = proxy.GetSecureDataSet("");  
   3. ds.AcceptChanges();  
   4.   
   5. //edit dataset  
   6.   
   7.   
   8. //get changes  
   9. DataSet editDataset = ds.GetChanges();  
  10.   
  11. //call update webmethod  
  12. proxy.SecureUpdateDataSet(editDataSet)  

But it finish with this error :

System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: Update requires a valid UpdateCommand when passed DataRow collection with modified rows. at WebService.Service.SecureUpdateDataSet(DataSet ds) in D:\Diploma.Work\WebService\Service1.asmx.cs:line 489

Problem is with SQL Commad, client can add, delete and insert row, how can write a corect SQL command.... any advice please? Thank you

A: 

I think SqlCommandBuilder is the better and convenient way for adding, updating and deleting data in the database through dataset.

ydobonmai
+1  A: 

try this:

[WebMethod]
public bool SecureUpdateDataSet(DataSet delta)
{

     string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;

     using(var conn = new SqlConnection(connStr))
     {
        conn.Open();

        string sql = "select * from tab1 where 1 = 0";

        using(var da = new SqlDataAdapter(sql, conn))
        {

            var builder = new SqlCommandBuilder(ad);

            da.InsertCommand = builder.GetInsertCommand();
            da.UpdateCommand = builder.GetUpdateCommand();
            da.DeleteCommand = builder.GetDeleteCommand();

            da.Update(delta);

            return true;
        }
    }
    return false;
}
Michael Buen
I think you should get the Primary/Unique key information as well before you fill the dataset by doing something like this or the update might fail:-da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
ydobonmai
-1: you should also put that `SqlDataAdapter` into a `using` block.
John Saunders
@John Saunders: why did you dwell on that point to downvote the solution? do you honestly practice that consistently on your every object allocation? i guess most of your code is very nested. the reason why i put connection on using clause is to make sure the database connection gets released immediately after performing the query. you know some database are licensed on connection basis? i trusts .NET's garbage collection or any managed language for that matter, so i don't see any point that all allocation should be subjected to using clause
Michael Buen
@Ashish Gupta: SqlDataAdapter will automatically fill the primary/unique key information to dataset if the source table already has primary/unique key. that is clearly evident from the answer here: http://stackoverflow.com/questions/1599230/anyway-see-why-i-get-this-concurrency-violation-in-these-few-lines-of-code/1604547#1604547
Michael Buen
@Michael: Yes, I always us a `using` clause for every `IDisposable` object I create and only use within a local scope (except WCF proxies, which are "special"). I also always doenvote when I see one not used. I see too much copy-and-paste development and resource leaks when `Dispose` is not called. Correct it and I reverse the downvote.
John Saunders
@John Saunders: Complied, this article made me remember that ADO.NET(all .NET objects) doesn't use reference counting(COM objects like ADO classic), **GC** doesn't automatically kick-in even the variable goes out of scope http://www.15seconds.com/issue/040830.htm "If you think of relying on connection objects to go out of scope, think again. It may take hours until GC collects them."
Michael Buen
@Michael: downvote removed.
John Saunders