WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Data Binding in ASP.NET 2.0
Pages: 1, 2, 3

Multiuser Updates

As things stand now, you read data from the database through the SqlDataSource and into your DataGrid. You have now added the ability to update (or delete) that information. Of course, more than one person may be interacting with the database at the same time. (Few web applications support only single-user access.) You can imagine that this could cause tremendous data corruption problems. Imagine, for example, that two people download a record:

Company: Liberty Associates, Inc. / City: Boston / Contact Name: Jesse Liberty 
The first editor changes the city from Boston to New York (never happen, I'm not moving back). The second editor changes the contact name from Jesse Liberty to Milo Liberty (my dog). Now things get interesting. The first editor writes back the data record, and the database has

Company: Liberty Associates, Inc. / City: New York / Contact Name: Jesse Liberty 

A moment later, the second person updates the database and the database now has

Company: Liberty Associates, Inc. / City: Boston / Contact Name: Milo Liberty 

These earlier updated values are overwritten, overwritten, and lost. The technical term for this is bad.

To prevent this kind of problem, you may use any of the following strategies:

  • Locking the records. When one user is working with a record, other users can read the records but cannot update them.

  • Updating only the columns you change. In the previous example, the first editor would have changed only the city, while the second editor would have changed only the name.

  • Previewing whether the database has changed before you make your updates. If it has, notify the user and don't make the change.

  • Attempting the change and handling the error, if any.

Odd as it may seem at first, it turns out that the best approach to managing concurrency is to try the update and then respond to errors as they arise. After all, most of the time there are no concurrency issues, and this is far faster and safer than the alternatives. For this approach to be effective, however, you must craft your Update command so that it will fail if someone else has updated the record in any way.

Since the data source can tell you the original values that it received from the database, you need pass only those values back into the stored procedure as parameters, and then add them to the Where clause in your Update command. When you update the record, the original values are checked against the values in the database. If they are different, no records will be updated until you fix the problem (which could only have been caused by someone else updating the records before you did).

The wizard makes this a snap. Reopen it and check the Use Optimistic Concurrency check box (look back to Figure 9). Click on OK. Click on Next and then on Finish. Once more, examine the HTML source code. It has become somewhat more complicated, as the Update command now checks to make sure the record is unchanged.

UpdateCommand="UPDATE [Customers] 
SET [CompanyName] = @CompanyName, 
    [ContactName] = @ContactName, 
    [ContactTitle] = @ContactTitle, 
    [Address] = @Address, 
    [City] = @City, 
    [Region] = @Region, 
    [PostalCode] = @PostalCode, 
    [Country] = @Country, 
    [Phone] = @Phone, 
    [Fax] = @Fax 
WHERE [CustomerID] = @original_CustomerID AND 
      [CompanyName] = @original_CompanyName AND 
      [ContactName] = @original_ContactName AND 
      [ContactTitle] = @original_ContactTitle AND 
      [Address] = @original_Address AND 
      [City] = @original_City AND 
      [Region] = @original_Region AND 
      [PostalCode] = @original_PostalCode AND 
      [Country] = @original_Country AND 
      [Phone] = @original_Phone AND 
      [Fax] = @original_Fax" 
 
<UpdateParameters>
    <asp:Parameter Name="CompanyName" Type="String" />
    <asp:Parameter Name="ContactName" Type="String" />
    <asp:Parameter Name="ContactTitle" Type="String" />
    <asp:Parameter Name="Address" Type="String" />
    <asp:Parameter Name="City" Type="String" />
    <asp:Parameter Name="Region" Type="String" />
    <asp:Parameter Name="PostalCode" Type="String" />
    <asp:Parameter Name="Country" Type="String" />
    <asp:Parameter Name="Phone" Type="String" />
    <asp:Parameter Name="Fax" Type="String" />
    <asp:Parameter Name="original_CustomerID" Type="String" />
    <asp:Parameter Name="original_CompanyName" Type="String" />
    <asp:Parameter Name="original_ContactName" Type="String" />
    <asp:Parameter Name="original_ContactTitle" Type="String" />
    <asp:Parameter Name="original_Address" Type="String" />
    <asp:Parameter Name="original_City" Type="String" />
    <asp:Parameter Name="original_Region" Type="String" />
    <asp:Parameter Name="original_PostalCode" Type="String" />
    <asp:Parameter Name="original_Country" Type="String" />
    <asp:Parameter Name="original_Phone" Type="String" />
    <asp:Parameter Name="original_Fax" Type="String" />
</UpdateParameters>

Creating the modified Update (and Delete) command is done for you, as is setting up the parameters, and the original values and new values are tracked automatically by the GridView.

Displaying and Updating the Grid

Now that your DataSource object is ready to go, you have only to set up your DataGrid. Step 1, click on the smart tag and choose Edit Columns, restoring the titles to the way you want.
Step 2, click on the smart tag's check boxes to enable editing and deleting, as shown in Figure 10.

Figure 10
Figure 10: Enabling Editing and Deleting

If you would prefer to have buttons for Edit and Delete rather than links, click on the smart tag and click on Edit Columns. When the fields dialog box opens, click on Selected Fields in the Command Field entry. This brings up the field properties in the right-hand window, where you can change the ButtonType from Link to Button, as shown in Figure 11.

Figure 11
Figure 11: Specifying the button type

The result is that the commands (Edit and Delete) are now displayed as buttons, as shown in Figure 12.

Figure 12
Figure 12: Our new buttons

Tracking the Update with Events

Some programmers get nervous when a control does so much work invisibly. After all, when all goes well, it's great not to have to sweat the details, but if something goes wrong, how can you tell whether your connection failed, no records were updated, an exception was thrown, or something else happened?

The ASP.NET controls overcome these concerns by providing numerous events that you can handle. For example, the DataGrid has almost two dozen events. There is an event that fires when you press the Save button after editing a row (RowUpdating) and there is a second event after the row has been updated (RowUpdated). There are events for when the data is about to be bound, as well as when it has been bound, when the row is created, when it is about to be deleted, when it has been deleted, and more.

To see this at work, you'll create an event handler for the RowUpdated event. The easiest way to do so is to click on Design View, then click on the grid. In the properties window, click on the lightning bolt and scroll to the RowUpdated event. Click in the box to the right of the event name. Visual Studio 2005 will create an event handler for you and put you in the text editor to implement the event.

protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)

Notice that the second argument to this method is of type GridViewUpdatedEventArgs. This object has useful information about the update, including:

  • a Boolean property, ExceptionHandled, that will be true if an exception was thrown when updating the data
  • the exception object itself
  • an integer telling you how many rows were affected by your update (RowsAffected)
  • three ordered collections:
    • Keys
    • OldValues
    • NewValues

Here's the exception handler:

protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
   if (e.ExceptionHandled)
   {
      string ex = e.Exception.Message; // display this?
   }
   else
   {
      int numRowsChanged = e.AffectedRows;
      foreach ( DictionaryEntry myDE in e.NewValues )
      {
         if (myDE.Value != null)
         {
            string key = myDE.Key.ToString();
            string val = myDE.Value.ToString();
         }
      }
   }
}

Conclusion

ASP.NET DataBinding has come a long way. The improved designer support for data binding makes it much easier in the next version of ASP.NET.

Jesse Liberty is a senior program manager for Microsoft Silverlight where he is responsible for the creation of tutorials, videos and other content to facilitate the learning and use of Silverlight. Jesse is well known in the industry in part because of his many bestselling books, including O'Reilly Media's Programming .NET 3.5, Programming C# 3.0, Learning ASP.NET with AJAX and the soon to be published Programming Silverlight.


Read more Liberty on Whidbey columns.

Return to ONDotnet.com.