MULTIMEDIA

Building LOB Applications : Implementing CRUD Operations in WCF Data Services

2/17/2011 11:48:19 AM

1. Problem

You need to have read-write access to data published via OData.

2. Solution

Take advantage of WCF Data Services enhancements such as DataServiceCollection available in Silverlight 4 to implement CRUD operations.

3. How It Works

WCF Data Services support entity tracking on the client so that you can submit a query to the service in order to populate a DataServiceCollection that is databound to a UI control such as a DataGrid. You used this technique in Recipe 1 to load read-only data. In this recipe, you do the same but there's a twist: now you can insert, update, and delete edits.

The code is covered in detail in the next subsection but here are the key points on how the code works. In this recipe, you edit order details for the Northwind database, first loading all of the Customers, the related Orders, and finally the related Order Detail line items. The code allows the user to do the following:

  • Delete the selected Order Details line item

  • Update the Quantity for an existing Order Details line item

  • Add an Order Details line item to an existing Order

You created a Service Reference to the Northwind Data Service in Recipe 2. The client-side proxy provides the NorthwindEntities type that inherits from System.Data.Services.Client.DataServiceContext. You create an instance of that class called NorhwindContext, running all queries and operations through the DataServiceContext instance. This is required in order to keep things synchronized across entities as you make edits.

Once you have the data context established, you go through the process of querying data and enabling edits. The code is very simple once you see the pattern. Essentially, you identify the object to be deleted, updated, or created and call methods on NorthwindContext to make it happen. The operation occurs locally in the DataServiceCollection instance of interest (i.e. the Order_Details entity) and then the changes are applied on the server via NorthwindContext.

4. The Code

Take advantage of the Northwind Data Service you created in Recipe 2 and add a service reference to make it available in Recipe 9-3's Silverlight application. In UserControl_Loaded you create a DataServiceContext instance named NorthwindContext as before. You add one directive to have NorthwindContext apply changes as a batch by updating SaveChangesDefaultOptions since the insert operation affects multiple tables, as shown here:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
NorthwindContext = new NorthwindEntities(
new Uri("DataService/NorthwindDataService.svc", UriKind.Relative));
NorthwindContext.SaveChangesDefaultOptions = SaveChangesOptions.Batch;
}

Next, you have a series of similar operations as in Recipe 1 and 2 where you load up three DataGrid instances with Customer data, Customer Order data, and finally the corresponding Customer Order Details data where you implement simple CRUD operations. (We don't go through the data loading code so as to not be redundant.) Essentially, when the user clicks the Load Northwind Customer Data button, it populates the Customers DataServiceCollection<Customer> instance that is databound to the top left DataGrid. The Load Customer Orders button loads the Orders that correspond to the selected Customer into the DataGrid on the upper right. The same process is implemented to load up the corresponding Order_Details in the DataGrid on the lower right. At this point, you have the data that you want to perform edits on in the Order_Details data. Next, add a UI for making edits with buttons that correspond to deleting, updating, and creating an Order_Details entity, as shown in figure 9-7.

Figure 1. The UI for Recipe 3

To load the data, simply clicked the Load Northwind Customer Data button, followed-by the Load Customer Orders button, and finally the Load Customer Order Details button. You can select a particular record before clicking the next step if desired to test it out but you must click the buttons in that order for the simple UI to function.

The Delete Selected Line Item button does what it suggests: it deletes the selected Order_Details record in the Customer Order Details DataGrid. Here is the event handler for the button:

private void DeleteDetailsItemBtn_Click(object sender, RoutedEventArgs e)
{

if (CustomerOrderDetailsDataGrid.SelectedItem != null)
{
NorthwindContext.DeleteObject(
(Order_Detail)CustomerOrderDetailsDataGrid.SelectedItem);
NorthwindContext.BeginSaveChanges(
SaveChangesOptions.Batch, ChangesSaved, NorthwindContext);
}
}

Since you have the Order_Details object to be deleted already on the client as part of the CustomerOrderDetails DataServiceCollection<Order_Detail> collection, you can simply pass in the DataGrid SelectedItem to DeleteObject and all of the change tracking magic on the client takes care of the rest. However, to push the changes to the server, call BeginSaveChanges on the NorthwindContext object which knows where the WCF Data Service lives and how to apply the changes.

The code to perform the update operation is a little bit more complicated but not much more. Here is the code:

private void UpdateDetailsItemBtn_Click(object sender, RoutedEventArgs e)
{
((Order_Detail)CustomerOrderDetailsDataGrid.SelectedItem).Quantity =
Convert.ToInt16(EditQuantity.Text);
NorthwindContext.UpdateObject(
(Order_Detail)CustomerOrderDetailsDataGrid.SelectedItem);

NorthwindContext.BeginSaveChanges(
SaveChangesOptions.Batch, ChangesSaved, NorthwindContext);
}

The code is similar except you call the NorthwindContext.UpdateObject method and pass in the modified object to complete the changes on the client and to mark the edited Order_Details entity as modified. You edit the selected Order_Details entity by updating the Quantity value to match what is entered in the EditQuantity TextBox.

The code to insert a new Order_Details entity as a child to the selected Customer Order is shown here:

private void InsertlineItemBtn_Click(object sender, RoutedEventArgs e)
{
Order_Detail od = new Order_Detail();
Order SelectedOrder = (Order)CustomerOrdersDataGrid.SelectedItem ;
Product SelectedProduct = (Product)ProductsDataGrid.SelectedItem ;
od.Order = SelectedOrder;
od.OrderID = SelectedOrder.OrderID;
od.Product = SelectedProduct;
od.ProductID = SelectedProduct.ProductID;
od.Quantity = Convert.ToInt16(InsertProdQuantity.Text);
od.UnitPrice = (Decimal)SelectedProduct.UnitPrice;

NorthwindContext.AddToOrder_Details(od);
NorthwindContext.BeginSaveChanges(ChangesSaved, NorthwindContext);
}

You have a small DataGrid on the left that lists all of the possible Products that you can add as a new line item to the selected Order. Otherwise, the code to create the new Order_Details entity is very straightforward. When the Service Reference client proxy is created, it automatically generates a method called AddToOrder_Details on the NorthwindContext variable where you pass in the new Order_Details entity to add the line item to the Order. As before, client-side changes are persisted to the service via the BeginSaveChanges method, which is very different when compared to the ADO.NET Entity Framework

The last item to mention is the ChangesSaved method that is called after changes are persisted by NorthwindContext shown here:

private void ChangesSaved(Object state)
{
EditsMessage.Text = "Selected Line Item Modified + " + DateTime.Now.ToString();
}


You simply update a string with a time stamp, but instead of passing in the NorthwindContext variable as the third parameter in the call below that is required to persist CRUD operations to the server, you could pass in a custom structure that has properties to identify more detail such as the type of operation, the name of the entity modified, etc., in order to provide a more robust status:

NorthwindContext.BeginSaveChanges(ChangesSaved, NorthwindContext);

Other  
 
Most View
Last Call For Blackberry? (Part 1)
101 Recommended Apps (Part 16)
Kindle Fire - The Second Coming (Part 2)
How To Make A Massive Synth Bass Sound (Part 5) : Commercial house bass with impOSCar
Visual Studio 2010 IDE : Using, Creating, and Managing Reusable Code Snippets
Best Bluetooth Speakers in April
Forget iPhoto - Use Pixa To Organize Photos On Your Mac
Lightweight Machines For Heavy Workloads (Part 4) - Toshiba Portege Z30T
Silverlight Recipes : Controls - Customizing the Default ListBoxItem UI
Windows 8 Storage Spaces (Part 2)
Top 10
SQL Server 2012 : Consolidating Data Capture with SQLdiag - Getting Friendly with SQLdiag (part 2) - Using SQLdiag as a Service
SQL Server 2012 : Consolidating Data Capture with SQLdiag - Getting Friendly with SQLdiag (part 1) - Using SQLdiag as a Command-line Application
SQL Server 2012 : Consolidating Data Capture with SQLdiag - The Data Collection Dilemma, An Approach to Data Collection
SQL Server 2012 : Troubleshooting Methodology and Practices - Data Analysis, Validating and Implementing Resolution
SQL Server 2012 : Troubleshooting Methodology and Practices - Data Collection
SQL Server 2012 : Troubleshooting Methodology and Practices - Defining the Problem
SQL Server 2012 : Troubleshooting Methodology and Practices - Approaching Problems
Windows 8 : Accessing System Image Backup and Recovery Functionality with Windows Backup, Cloud Backup
Windows 8 : Using the Windows 8 Recovery Tools (part 2) - Push Button Reset
Windows 8 : Using the Windows 8 Recovery Tools (part 1) - Creating a System Recovery Disc, Booting to the Windows Recovery Environment