Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.


  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

10. Talking to REST and WCF Data Service... > Reading data using WCF Data Services

Reading data using WCF Data Services

Reading data using WCF Data Services Applies to Silverlight 3, 4 and 5 Let's assume we have decided that WCF Data Services is going to be the technology to get data inside our Silverlight application, which admittedly is a great choice. In the previous recipe, we saw how we can set up Silverlight to use WCF Data Services. However, we didn't actually exchange any data with the service (which is quite ironic for a data service). In this recipe, we'll perform read operations on the data by building on the code created in the previous recipe. This time, we'll focus on the Computer data in the database. Getting ready This recipe continues on the code created in the previous recipe. If you want to follow along, you can continue using your code, or use the provided starter solution located in the Chapter10/WorkingWithWcfDataServices_Reading_Starter folder in the code bundle available on the Packt website. The finished solution for this recipe can be found in the Chapter10/WorkingWithWcfDataServices_Reading_Completed folder. How to do it... In the previous recipe, we introduced the client library that dramatically reduces the amount of code that we need to write compared to plain REST services. Using this library, we can load data in several formats, such as an entire list, a single object with or without related entities, and so on. We'll build an application that shows a list of computers. The details of each computer can be seen using a detail screen. Perform the following steps to start reading data from WCF Data Services: The XAML for the application is similar to the XAML we used in the previous recipes. The application's UI mainly consists of a DataGrid with defined columns. The code for this DataGrid can be found in the code bundle. Thanks to the client library, we have the ability to write LINQ queries. These LINQ queries are executed using an instance of the context, so creating this context instance should be our first step. Note that the context instance accepts a URI to the .svc file of the service as a parameter. After this, we can write a LINQ query, in which we load all Computer entities. A little caution though: WCF Data Services wouldn't load the related Manufacturer objects by default, although we want to show this information as well in the DataGrid. Therefore, we specify this using the Expand method as shown in the following: ComputerInventoryEntities context=new ComputerInventoryEntities (new Uri("ComputerInventoryService.svc", UriKind.Relative)); public MainPage() { InitializeComponent(); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { ComputerLoadStart(); } private void ComputerLoadStart() { var query = from c in context.Computer.Expand("Manufacturer") select c; } While the query looks rather normal, do keep in mind that all Silverlight's service requests are carried out asynchronously. Therefore, the query is cast to a DataServiceQuery<T> (in this case, the return type T is Computer). On this instance, the BeginExecute method is called, which triggers an asynchronous call to the service. Similar to other asynchronous calls, a callback method is passed in. The query itself is also passed in, so we have access to it in the callback method. This is shown in the following code: private void ComputerLoadStart() { DataServiceQuery<Computer> dsq = (DataServiceQuery<Computer>)query; dsq.BeginExecute(ComputerLoadCompleted, dsq); } When the service is ready, the ComputerLoadCompleted callback method is invoked. This method receives an IAsyncResult instance as parameter, which contains the DataServiceQuery<T>. By calling the EndExecute method on this instance, we get access to the returned Computer instances. We place these instances in an ObservableCollection called computerCollection for data binding purposes. The collection is bound to the DataGrid using the ItemsSource property as shown in the following code: ObservableCollection<Computer> computerCollection = new ObservableCollection<Computer>(); private void ComputerLoadCompleted(IAsyncResult asr) { DataServiceQuery<Computer> dsq = (DataServiceQuery<Computer>)asr.AsyncState; foreach (var computer in dsq.EndExecute(asr).ToList()) { computerCollection.Add(computer); } ComputersDataGrid.ItemsSource = computerCollection; } Let's now take a look at the detail page. When clicking on a View button in the grid, we load a Silverlight Child Window named ComputerDetailView.xaml that features a nice zoom-in effect when opened. The XAML for this window is straightforward and can be found in the code bundle.To show the details of the selected computer in the DataGrid, we pass the context as well as the computerID of the selected computer via the constructor. This is shown in the following code: private ComputerInventoryEntities context; private int computerId; private Computer computer; public ComputerDetailView(ComputerInventoryEntities context, int computerId) { InitializeComponent(); this.context = context; this.computerId = computerId; LoadComputer(); } In the LoadComputer method, we load the details of the selected computer. However, the computer is already being tracked by the context because of the list display, but not all the data we need is loaded (the computer type is omitted in the list). Thus, we need to explicitly tell the context that it has to reload the computer using the OverWriteChanges of the MergeOption enumeration. The following code shows this loading process: private void LoadComputer() { context.MergeOption = MergeOption.OverwriteChanges; var query = from c in context.Computer.Expand("ComputerType") where c.ComputerId == computerId select c; DataServiceQuery<Computer> dsq = (DataServiceQuery<Computer>)query; dsq.BeginExecute(ComputerLoadCompleted, dsq); } private void ComputerLoadCompleted(IAsyncResult asr) { DataServiceQuery<Computer> dsq = (DataServiceQuery<Computer>)asr.AsyncState; computer = dsq.EndExecute(asr).FirstOrDefault<Computer>(); ComputerDetailGrid.DataContext = computer; } After all the previous code is added, we have successfully created a master-detail implementation based on WCF Data Services. The detail screen is shown in the following image: How it works... The most important part of this recipe is the LINQ query. When executing a LINQ query against a WCF Data Service, the query is translated into a format that the service understands—a URI. All the options we specify in the query are translated into the URI. The URI to which a request is sent is http://127.0.0.1:8624/ComputerInventoryService.svc/Computer()?$expand=Manufacturer. (This can be seen using Fiddler2. More information on this tool can be found in Appendix C.) Note Note that the Expand option instructs the service to retrieve all Computer instances, and expand the results to include the related Manufacturer instances for each Computer instance. This process is called eager loading. In this process, we explicitly ask to load the related entities initially. If we omit eager loading, the property will have a null value. To see what the AtomPub (XML) response of the service looks like, simply copy/paste the previously mentioned URI in your browser or view it in Fiddler2. The context is the real workhorse in this recipe. It keeps track of all the loaded items (this is called object tracking). However, sometimes we need to ask for a complete reload. In the example at hand, we need to do so in the detail screen. We have the MergeOption enumeration at our disposal for this. The OverwriteChanges explicitly tells the context that it should replace the item loaded in the context. There's more... We might know that there are related entities, but not want to load them initially. We can load on demand using the LoadProperty method. This method is used in the detail screen of the application. When loading, the allowed users are not retrieved automatically (for example, not to stress the database). By clicking on the Load button, we load them asynchronously on demand using the LoadProperty method. The result is that the Computer entity will have its property filled with the related User entities. This is shown in the following code: private void LoadUsersButton_Click(object sender, RoutedEventArgs e) { context.BeginLoadProperty(computer, "User", UsersLoadCompleted, null); } private void UsersLoadCompleted(IAsyncResult asr) { context.EndLoadProperty(asr); // do something with the loaded values here } See also In the Reading data from ADO.NET Data Services recipe, we create the ADO.NET Data Service and set up communication with it.

  

You are currently reading a PREVIEW of this book.

                                                                                                                    

Get instant access to over $1 million worth of books and videos.

  

Start a Free Trial


  
  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint