Last week I wrote a post about Introduction to WCF Data Services and OData and I said I will write a post showing how to access an OData feed from a Silverlight application and this is it.
I will start off by creating a Silverlight Application and I am creating a new web project to host my Silverlight application. I have NuGet installed in my Visual Studio and since I need OData library, in the Package Manager Console I am running the following command.
PM> Install-Package Microsoft.Data.Services –Pre
Package Manager Console |
Install OData Library |
And then I can see the following references are added to my web project.
- Microsoft.Data.Edm
- Microsoft.Data.OData
- Microsoft.Data.Services
- Microsoft.Data.Services.Client
References |
Now I am adding a ADO.NET Entity Data Model to my web project (right click and add new item ) and I am naming it as DBEntities. Please note that I have a sample table to store Customer information and has following columns.
- CUSTOMER_ID (int) – Primary Key
- CUSTOMER_FIRST_NAME (string)
- CUSTOMER_LAST_NAME (string)
ADO.NET Entity Data Modal : Choose Data Connection |
ADO.NET Entity Data Modal : Choose Database Objects |
Now I am adding a WCF Data Service to my web project and I am naming it as DBService.
Add WCF Data Service |
I will be getting something like this.
Modify WCF Data Service |
I can see some errors, because there is ambiguous reference and that’s because System.Data.Services and System.Data.Services.Client are included in OData library. So I need to delete
System.Data.Services and System.Data.Services.Client from references.
Remove References |
Now I am modifying the class as follows.
public class DBService : DataService<DBEntities> { // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config) { // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. // Examples: config.SetEntitySetAccessRule("CUSTOMERs", EntitySetRights.All); // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; } }
In here I have put DBEntities as “ /* TODO: put your data source class name here */ ” and I have uncommented config.SetEntitySetAccessRule method. Here “CUSTOMERs” is a ObjectSet created for my table “CUSTOMER”. You can check it by examining the code file of your created ADO.NET Entity Data Model. I have changed EntitySetRights.AllRead to EntitySetRights.All, because I am planning to Read and Write to the entity.
Now I am pretty much done modifying the items in the web project and now I am starting to modify my Silverlight Application.
First I will add a Service Reference to the DBService in my web project.
Now I am pretty much done modifying the items in the web project and now I am starting to modify my Silverlight Application.
First I will add a Service Reference to the DBService in my web project.
Service Reference |
Now I am modifying my MainPage.xaml. I have created some controls.
Sample Application |
My combo box is binded and other controls are just there. XAML code for binding the combo box is,
<!--I am binding the combobox and the display field should be customer ID--> <ComboBox Height="23" ItemsSource="{Binding}" DisplayMemberPath="CUSTOMER_ID" HorizontalAlignment="Left" Margin="101,109,0,0" Name="cboCustomer" VerticalAlignment="Top" Width="165" SelectionChanged="cboCustomer_SelectionChanged" />
Now I am writing the code in the code behind of the MainPage.xaml. Rather explaining one by one, I am pasting the code here with comments.
using System; using System.Data.Services.Client; using System.Linq; using System.Windows; using System.Windows.Controls; using WCFDataServicesSilverlightApp.svcDBService; // service referencenamespace WCFDataServicesSilverlightApp { public partial class MainPage : UserControl { // DataServiceContext DBEntities oDBEntities; // dynamic entity collection of customers DataServiceCollection<CUSTOMER> resultColl; // relative path of the service private const string ServiceUri = "/DBService.svc"; public MainPage() { InitializeComponent(); Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { // in Page load I am retrieving the existing customer list and // filling up my combo box. LoadCustomers(); } private void LoadCustomers() { // create the DataServiceContext using the service URI. oDBEntities = new DBEntities(new Uri(ServiceUri, UriKind.Relative)); // linq query to retrieve all the customers. var query = from c in oDBEntities.CUSTOMERs select c; resultColl = new DataServiceCollection<CUSTOMER>(); // I am loading the collection asynchronously because I don't need // my page to be stucked while loading customers. resultColl.LoadAsync(query); // while loading the customer I am showing a busy indicator. busyIndicator1.IsBusy = true; // event to be raised when the loading is completed. resultColl.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(ResultColl_LoadCompleted); // DataContext for binding the combobox. DataContext = resultColl; cboCustomer.DataContext = DataContext; } private void cboCustomer_SelectionChanged(object sender, SelectionChangedEventArgs e) { oDBEntities = new DBEntities(new Uri(ServiceUri, UriKind.Relative)); // when selected index is changed, I am retrieving the information of the // selected the customer. var query = from c in oDBEntities.CUSTOMERs where c.CUSTOMER_ID == ((CUSTOMER) cboCustomer.SelectedValue).CUSTOMER_ID select c; resultColl = new DataServiceCollection<CUSTOMER>(); // I am loading the collection asynchronously. resultColl.LoadAsync(query); // event to be raised when the loading is completed. resultColl.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(ResultColl_LoadCompleted); } void ResultColl_LoadCompleted(object sender, LoadCompletedEventArgs e) { // loading completed. busyIndicator1.IsBusy = false; // if loading is cancelled or if there is an error show some message. if (e.Cancelled || e.Error != null) { MessageBox.Show("Error loading customer."); } else { if (resultColl != null) { if (cboCustomer.SelectedValue != null) { // setting up the information. txtFirstName.Text = resultColl[0].CUSTOMER_FIRST_NAME; txtLastName.Text = resultColl[0].CUSTOMER_LAST_NAME; } } } } private void btnAdd_Click(object sender, RoutedEventArgs e) { CUSTOMER customer; // adding a customer. // Create always needs a Primary Key. // Since my ID column is an Identity Column in SQL, ID is auto generated and auto incremented // I am passing some integer value. customer = CUSTOMER.CreateCUSTOMER(-1); // set property values. customer.CUSTOMER_FIRST_NAME = txtFirstName.Text; customer.CUSTOMER_LAST_NAME = txtLastName.Text; AddRecord(customer); } private void btnUpdate_Click(object sender, RoutedEventArgs e) { // get selected customer. CUSTOMER customer = resultColl[0]; // changing the property values. customer.CUSTOMER_FIRST_NAME = txtFirstName.Text; customer.CUSTOMER_LAST_NAME = txtLastName.Text; UpdateRecord(customer); } private void btnDelete_Click(object sender, RoutedEventArgs e) { // get selected customer. CUSTOMER customer = resultColl[0]; DeleteRecord(customer); } private void AddRecord(CUSTOMER customer) { // add the new customer to the customer entity set. oDBEntities.AddToCUSTOMERs(customer); // asynchronously start saving and OnChangesSaved will be called when completed. oDBEntities.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, oDBEntities); } private void UpdateRecord(CUSTOMER customer) { // update selected customer in the customer entity set. oDBEntities.UpdateObject(customer); // asynchronously start saving and OnChangesSaved will be called when completed. oDBEntities.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, oDBEntities); } private void DeleteRecord(CUSTOMER customer) { // delete selected customer from customer entity set. oDBEntities.DeleteObject(customer); // asynchronously start saving and OnChangesSaved will be called when completed. oDBEntities.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, oDBEntities); } private void OnChangesSaved(IAsyncResult result) { // this will be showed when asynchronous BeginSaveChanges is completed. MessageBox.Show("Done."); } } }
And that's it. Hope this helps.
Happy Coding.
Regards,
Jaliya
Happy Coding.
Regards,
Jaliya
No comments:
Post a Comment