[ Team LiB ] |
15.3 Updating a Data Source Using Custom LogicThe CommandBuilder provides an extremely convenient way to create the required Command objects, but it has definite limitations. Here are some reasons to avoid the CommandBuilder and use your own custom updating logic:
There is only one real difference between using the CommandBuilder and custom update logic. The CommandBuilder generates the DeleteCommand, InsertCommand, and UpdateCommand objects used by the DataAdapter to reconcile changes made to the DataSet with the data source. With custom update logic, those update objects have to be defined. The SourceColumn and SourceVersion properties of the Parameter object bind associate a Parameter with a DataColumn. The DataAdapter uses these properties to determine the source of the values within the DataRow; these values are loaded into the Parameter for the appropriate update Command for the DataRow before the update is performed for the row. The default value for SourceVersion is the Current row, so this value needs to be set only when a different version is required. The following two examples illustrate the effect of the SourceColumn and SourceVersion properties. The first example maps the CustomerID column from the Current version of the DataRow to the Parameter named @CustomerID: params.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); The second example maps the OrderID column from the Original version of the DataRow to the Parameter named @OrderID: params.Add("@OrderID", SqlDbType.Int, 0, "OrderID"); params["@OrderID"].SourceVersion = DataRowVersion.Original; It's important to understand that this mapping occurs each time a row is updated and is defined separately for each update Command object. The actual Command object that updates a particular row when the Update( ) method is called is based on the DataRowState of that row. The update Command objects can be based on parameterized SQL statements, as is demonstrated by CommandBuilder, or on stored procedures, as is more commonly the case. One obvious drawback to using SQL statements is that updated values in the data source can't be returned back to the DataSet. Refreshing the DataSet after an update using stored procedures is discussed in more detail later in this chapter. The following example uses the Orders table from Northwind database to demonstrate how to use stored procedures to define the update Command objects and then how to use these custom update Command objects. The stored procedures are presented first followed by the code that uses these stored procedures. Example 15-1 uses the stored procedures that delete, select, insert and update the data source. Example 15-1. Stored procedures for commands-- stored procedure for DeleteCommand CREATE PROCEDURE DeleteOrders @OrderID int AS SET NOCOUNT ON delete from Orders where OrderID=@OrderID return GO --stored procedure for SelectCommand CREATE PROCEDURE GetOrders AS SET NOCOUNT ON select OrderID, CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry from Orders return GO --stored procedure for InsertCommand CREATE PROCEDURE InsertOrders @OrderID int output, @CustomerID nchar(5), @EmployeeID int, @OrderDate datetime, @RequiredDate datetime, @ShippedDate datetime, @ShipVia int, @Freight money, @ShipName nvarchar(40), @ShipAddress nvarchar(60), @ShipCity nvarchar(15), @ShipRegion nvarchar(15), @ShipPostalCode nvarchar(10), @ShipCountry nvarchar(15) AS SET NOCOUNT ON insert Orders( CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry) values ( @CustomerID, @EmployeeID, @OrderDate, @RequiredDate, @ShippedDate, @ShipVia, @Freight, @ShipName, @ShipAddress, @ShipCity, @ShipRegion, @ShipPostalCode, @ShipCountry) if @@rowcount=0 return 1 set @OrderID=Scope_Identity() select @OrderId OrderId return GO --stored procedure for UpdateCommand CREATE PROCEDURE UpdateOrders @OrderID int, @CustomerID nchar(5), @EmployeeID int, @OrderDate datetime, @RequiredDate datetime, @ShippedDate datetime, @ShipVia int, @Freight money, @ShipName nvarchar(40), @ShipAddress nvarchar(60), @ShipCity nvarchar(15), @ShipRegion nvarchar(15), @ShipPostalCode nvarchar(10), @ShipCountry nvarchar(15) AS SET NOCOUNT ON update Orders set CustomerID = @CustomerID, EmployeeID = @EmployeeID, OrderDate = @OrderDate, RequiredDate = @RequiredDate, ShippedDate = @ShippedDate, ShipVia = @ShipVia, Freight = @Freight, ShipName = @ShipName, ShipAddress = @ShipAddress, ShipCity = @ShipCity, ShipRegion = @ShipRegion, ShipPostalCode = @ShipPostalCode, ShipCountry = @ShipCountry where OrderID = @OrderID if @@rowcount = 0 return 1 return GO Example 15-2 demonstrates how to create the update Command objects that retrieve and update the data, configure the stored procedure parameters, create the DataAdapter, and assign the command objects to the data adapter. Example 15-2. Creating update objects// connection and select command strings String connString = "Data Source=(local);Integrated security=SSPI;" + "Initial Catalog=Northwind;"; SqlConnection conn = new SqlConnection(connString); // create command objects using stored procedures SqlCommand selectCommand = new SqlCommand("GetOrders", conn); selectCommand.CommandType = CommandType.StoredProcedure; SqlCommand deleteCommand = new SqlCommand("DeleteOrders", conn); deleteCommand.CommandType = CommandType.StoredProcedure; SqlCommand insertCommand = new SqlCommand("InsertOrders", conn); insertCommand.CommandType = CommandType.StoredProcedure; SqlCommand updateCommand = new SqlCommand("UpdateOrders", conn); updateCommand.CommandType = CommandType.StoredProcedure; // set up the parameters SqlParameterCollection cparams; // delete command parameters cparams=deleteCommand.Parameters; cparams.Add("@OrderID", SqlDbType.Int, 0, "OrderID"); cparams["@OrderID"].SourceVersion=DataRowVersion.Original; // insert command parameters cparams = insertCommand.Parameters; cparams.Add("@OrderID", SqlDbType.Int, 0, "OrderID"); cparams["@OrderID"].Direction = ParameterDirection.Output; cparams["@OrderID"].SourceVersion = DataRowVersion.Original; cparams.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); cparams.Add("@EmployeeID", SqlDbType.Int, 0, "EmployeeID"); cparams.Add("@OrderDate", SqlDbType.DateTime, 0, "OrderDate"); cparams.Add("@RequiredDate", SqlDbType.DateTime, 0, "RequiredDate"); cparams.Add("@ShippedDate", SqlDbType.DateTime, 0, "ShippedDate"); cparams.Add("@ShipVia", SqlDbType.Int, 0, "ShipVia"); cparams.Add("@Freight", SqlDbType.Money, 0, "Freight"); cparams.Add("@ShipName", SqlDbType.NVarChar, 40, "ShipName"); cparams.Add("@ShipAddress", SqlDbType.NVarChar, 60, "ShipAddress"); cparams.Add("@ShipCity", SqlDbType.NVarChar, 15, "ShipCity"); cparams.Add("@ShipRegion", SqlDbType.NVarChar, 15, "ShipRegion"); cparams.Add("@ShipPostalCode", SqlDbType.NVarChar, 10, "ShipPostalCode"); cparams.Add("@ShipCountry", SqlDbType.NVarChar, 15, "ShipCountry"); // update command parameters cparams = updateCommand.Parameters; cparams.Add("@OrderID", SqlDbType.Int, 0, "OrderID"); cparams["@OrderID"].SourceVersion=DataRowVersion.Original; cparams.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); cparams.Add("@EmployeeID", SqlDbType.Int, 0, "EmployeeID"); cparams.Add("@OrderDate", SqlDbType.DateTime, 0, "OrderDate"); cparams.Add("@RequiredDate", SqlDbType.DateTime, 0, "RequiredDate"); cparams.Add("@ShippedDate", SqlDbType.DateTime, 0, "ShippedDate"); cparams.Add("@ShipVia", SqlDbType.Int, 0, "ShipVia"); cparams.Add("@Freight", SqlDbType.Money, 0, "Freight"); cparams.Add("@ShipName", SqlDbType.NVarChar, 40, "ShipName"); cparams.Add("@ShipAddress", SqlDbType.NVarChar, 60, "ShipAddress"); cparams.Add("@ShipCity", SqlDbType.NVarChar, 15, "ShipCity"); cparams.Add("@ShipRegion", SqlDbType.NVarChar, 15, "ShipRegion"); cparams.Add("@ShipPostalCode", SqlDbType.NVarChar, 10, "ShipPostalCode"); cparams.Add("@ShipCountry", SqlDbType.NVarChar, 15, "ShipCountry"); // create the data adapter SqlDataAdapter da = new SqlDataAdapter(selectCommand.CommandText, conn); // assign the custom update logic to the DataAdapter da.DeleteCommand = deleteCommand; da.InsertCommand = insertCommand; da.UpdateCommand = updateCommand; // create a new DataSet to receive the data and load the data DataSet ds = new DataSet(); da.Fill(ds, "Orders"); // ... code to modify the DataSet // update the data source using the custom update logic da.Update(ds, "Orders"); |
[ Team LiB ] |