Working with Data in Silverlight 2 (Entity Framework, Ado.Net Data Services, and DataGrid)

[Cross posted from: SilverlightForBusiness.net ]

Since the announcement from Tim Mallalieu (Program Manager, LINQ to SQL and Entity Framework) that “as of NET 4.0 the Entity Framework will be our recommended data access solution for LINQ to relational scenarios” your first decision on how to get data into and out of your databases has been made easier: EF is the way to go when looking at solutions from Microsoft (of course you may still decide that you would prefer to use something else from a third party, perhaps LLBLGEN, or maybe a hand crafted solution?).

But after that decision you still have another before we get the data anywhere Silverlight – how to “surface” or expose it.  Here you could use a WCF service with a basicHttpBinding a-la the “Silverlight enabled wcf service” template offered to us by Visual Studio 2008 with the Silverlight tools installed.

However a more interesting approach and one that appears to be a better fit with the way Alexandria (i.e. Silverlight 3) will work is to use an Ado.Net Data Service.

So what is an Ado.Net Data Service?  The documentation provides an nice summary:

The goal of the ADO.NET Data Services framework is to facilitate the creation of flexible data services that are naturally integrated with the web. As such, ADO.NET Data Services use URIs to point to pieces of data and simple, well-known formats to represent that data, such as JSON and ATOM (XML-based feed format). This results in the data service being surfaced as a REST-style resource collection that is addressable with URIs and that agents can interact with using standard HTTP verbs such as GET, POST, PUT or DELETE.

So that means that we can surface our data very simply via a REST interface.  Bottom line – you don’t have to write a whole load of methods in your service such as GetProducts, GetProductsById, GetOrder(int Id), UpdateOrder etc etc.  Instead you simple expose your data model through the service.

At this point I usually hear a gasp of belief – “what all our data is available read/write over the web?” – erm yes, but only if you choose not to lock it down.  Ado.Net Data Services combined with the EF give you plenty of scope to control access to data based on a users authentication and to inject business and validation logic.  But that is a blog post for another time.

What I think is particularly interesting from Silverlight when you use this combination of EF and ADO.Net Data Services is that the code you write feels as if you are writing it on the same tier as the database and application logic – in fact, it is not much different, and that is quite compelling.  It makes the classic find data, edit it with business logic applied, and sent back to the database quite easy (with a few gotcha’s which I will list below)

When I show this to delegates on a course who are used to using the Asp.Net Datagrid it gets another gasp, but this time in a positive way (well maybe not a gasp -  but certainly a look of bewilderment that belies the effort that have had to put into doing the same thing in Asp.net previously).

Ok so lets see a little code – I am going to demonstrate editing data from the Products table in the Northwind sample database.

I created a Silverlight Project then added a Ado.Net Entity Data Model to the web site and used the Wizard to add all the tables in the Northwind database to it. At this point you will most likely want to at least add some validation logic, or for more complex systems, extend the model.  I will cover this is later posts, but for now you can get more info on using EF from zeeshanhirani's free entity framework learning guide.pdf  including a walkthrough on this very item.  The msdn documentation is getting better too.

image

Next we add an Ado.Net Data Service to the web site and configure it to use our Entities type (in this case NorthwindEntities).  Also in the example below I have allowed full read/write access to all the data in the model (gasp!).  For more info on controlling access to the entities see the msdn documentation and I will be blogging about this in more details later.

public class NorthwindDataService : DataService< NorthwindEntities >
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(IDataServiceConfiguration config)
    {
        // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
        // Examples:
         config.SetEntitySetAccessRule("*", EntitySetRights.All);
         config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
    }
}

 

 

Ok we have our data available.  At this point you can browse the svc file and see your data exposed as ATOM. 

image

You can try navigating through the data by using the Url.  For example try the following (changing the port to your own web site of course :-)

image

image

 

 

image

Although this looks like read-only data, the service supports updates too through other HTTP verbs (e.g PUT).  So lets put that to the test by adding a service reference to Silverlight and creating an editable grid for the Products table (we will just edit one column for reasons that will become clear).

In the Silverlight project select Add Service Reference, click Discover and give it appropriate name (e.g. NorthwindDataService).  This will build a proxy class for us that supports the Ado.Net Data Service in Silverlight.

image

We are going to use the DataGrid to display and edit the data.  What we want to do is bind the data from our service to the DataGrid, use the grid to edit it, then send the changes back in a batch update.  Currently the DataGrid has a few issues, not least we do not have an event that lets us know when row data has been edited (this was available in beta’s of the grid but was removed in the final release – a strange decision, one that I would expect to be resolved sometime in the future).  To stack up another blog post with the others I have declared in this post, I will take a look at the free AgDataGrid from DevExpress in a later post which does not suffer from this.  We will work around this problem by using a DataTemplate and attaching to the LostFocus event of the TextBox that we will use to edit the data. 

Here is the Xaml for our UI (if you can call it that – just a couple of buttons and a one column grid)

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="30"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal">
        <Button Content="Get data " Click="Button_Click" Margin="5"  ></Button>
        <Button Content="Save data " Click="Button_Click_1" Margin="5"></Button>
    </StackPanel>

    <data:DataGrid x:Name="DataGrid1"  AutoGenerateColumns="False" Grid.Row="1">
        <data:DataGrid.Columns >

            <data:DataGridTemplateColumn Header="Product">
                <data:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding ProductName, Mode=TwoWay}"></TextBlock>
                    </DataTemplate>
                </data:DataGridTemplateColumn.CellTemplate>
                <data:DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox LostFocus="TextBox_LostFocus" Tag="{Binding ProductID}" 
                                 Text="{Binding ProductName, Mode=TwoWay}" ></TextBox> </DataTemplate> </data:DataGridTemplateColumn.CellEditingTemplate> </data:DataGridTemplateColumn> </data:DataGrid.Columns> </data:DataGrid> </Grid>

In the code behind we will need to instantiate our service as a class scoped variable.  Notice that the constructor takes a Uri pointing to the svc file we want to use.

NorthwindDataService.NorthwindEntities entities = 
                  new NorthwindDataService.NorthwindEntities(new Uri("NorthwindDataService.svc",UriKind.Relative));

We can then use the DataServicesQuery type to create and execute a query when the Get Data button is clicked.  Ideally we would just bind the results to the DataGrid, but this does not currently work, so instead I am also storing the results of the query in a List<Products> and binding that – this is really a hack to get around the DataGrid problem.

private List<Products> loadedProducts;
private void Button_Click(object sender, RoutedEventArgs e)
 {
     DataServiceQuery<Products> query = (DataServiceQuery<Products>)
         from c in entities.Products
         where c.Discontinued ==false
                 select c;
     DataGrid1.ItemsSource = null;
     query.BeginExecute(new AsyncCallback(c =>
     {
         IEnumerable<Products> results= query.EndExecute(c);
         loadedProducts = results.ToList();
         DataGrid1.ItemsSource = loadedProducts;
         
     }),query);

     
 }

 

Ok so when this button is clicked the DataGrid will show the result of the query using it’s DataTemplate:

image

Selecting a cell, then clicking again in it will switch the DataGrid it to edit mode (or you could double-click, but that’s not very web ui ;-).  After the data is edited we want to update our entity data with the changes.  Ideally the DataGrid would do this for us automatically, but unfortunately it does not at the moment, so instead we have hooked the LostFocus event on the textbox:

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
    
        int changedItemId = (int)((TextBox)sender).Tag;
        Products changedItem = (from c in loadedProducts
                                where c.ProductID == changedItemId
                                select c).Single();
        entities.UpdateObject(changedItem);
        

}

You will notice that in the DataTemplate for the grid, I embedded the ID for the item in a tag property for the TextBox – I am using this to find the actual product data in the List<Products> we populated when we got the data.  We then call UpdateObject on our entities object and pass the updated item to it.  This has not made any call to the database at this point, just updated our –in-memory entities collection.

Our Save Data event handler looks like the following, most of which is examining the OperationalResponses fro the Ado.Net Data service for exceptions.  The nice bit is that we only need to call BeginSaveChanges on our entities object to update all the changes in the database.

entities.BeginSaveChanges(SaveChangesOptions.ContinueOnError, new AsyncCallback(c =>
           {
               try
               {
                   DataServiceResponse response = entities.EndSaveChanges(c);
                   var operationalResponses = response.GetEnumerator();
                   while (operationalResponses.MoveNext() == true)
                   {
                       MessageBox.Show(operationalResponses.Current.StatusCode + " " + operationalResponses.Current.Error);
                   }
                   MessageBox.Show("Saved");
               }
               catch (DataMisalignedException ex)
               {
                   MessageBox.Show("Misaligned " + ex.Message);
               }
               catch (DataServiceClientException ex)
               {
                   MessageBox.Show("Client " + ex.Message);
               }
               catch (DataServiceRequestException ex)
               {
                   MessageBox.Show("Request " + ex.Message);
                   var operationalResponses = ex.Response.GetEnumerator();
                   while (operationalResponses.MoveNext() == true)
                   {
                       string message = string.Empty;
                       if (operationalResponses.Current.Error != null)
                       {
                           message = operationalResponses.Current.Error.Message;
                       }
                       message += " Status code: " + operationalResponses.Current.StatusCode;
                       MessageBox.Show(message);
                   }
               }
               catch (DataServiceQueryException ex)
               {
                   MessageBox.Show("Query " + ex.Message);
               }
           }), entities);

I hope that has given you an insight to using data with Silverlight 2 – I will be adding more posts to drill deeper into these topics, but you may want to look at the Msdn docs for this for further info

I have uploaded this sample project to my skydrive here: http://cid-fb8b852ef1ab0b35.skydrive.live.com/self.aspx/SampleCode/SilverlightSimpleEditData.zip  

posted @ Sunday, December 07, 2008 6:48 PM

Print

Comments on this entry:

# uauxxgkz

Left by uauxxgkz at 2/16/2009 4:23 PM
Gravatar
uauxxgkz

# Soma.

Left by Soma online sales. at 7/8/2009 6:52 AM
Gravatar
Soma drug history. Rise against soma tickets. Cheapest soma. Soma intimates. Drug soma. Soma online sales. Soma fm.

# Vicodin.

Left by Vicodin. at 7/8/2009 11:06 PM
Gravatar
Vicodin. Vicodin withdrawal.

# Soma.

Left by Aura soma bottles. at 7/9/2009 10:39 PM
Gravatar
Soma cube. Soma intimates stores. Soma sun pilates. Soma beds.

# Does xanax make sex better.

Left by Xanax with 5-htp. at 7/10/2009 10:46 PM
Gravatar
Hysbysfwrdd cymrux xanax cheap phentermine. Xanax dosage. Xanax online without prescription. Xanax.

# Percocet.

Left by Side effects of percocet. at 7/11/2009 10:43 PM
Gravatar
Percocet 93-490. Effects of long term percocet use. Identify percocet 93-490. Dosages for percocet. Percocet. How do i get off percocet.

# Twinlab with ephedra.

Left by Baltimore ephedra lawyers. at 7/12/2009 11:06 PM
Gravatar
Ephedra dangers. Ephedra diet pills.

# Percocet.

Left by Percocet with other drugs. at 7/13/2009 11:13 PM
Gravatar
Percocet online. Canadian prescritions and percocet. Can percocet cause nightmares. Will percocet show up in a drug test. Percocet. Percocet vs. lortabs.

# Soma to florida.

Left by Soma prozac. at 7/14/2009 11:14 PM
Gravatar
Ashes of soma. Soma muscle relaxant. Soma. Soma without prescription 180 count. Ashes of soma lyrics. Soma san diego. Soma beds. Prozac soma zoloft prozac onlineprescription.md.

# Tramadol dog.

Left by Tramadol. at 7/17/2009 1:23 AM
Gravatar
Tramadol hcl.

# fix your credit

Left by fix your credit at 12/26/2009 5:11 PM
Gravatar
I have to put a bookmark on this website!
Comments have been closed on this topic.
«February»
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213