Silverlight and RIA Services - Part II

Posted by: Malcolm Sheridan , on 8/21/2009, in Category Silverlight 2, 3, 4 and 5
Views: 24519
Abstract: In part II of this article I’ll demonstrate how to use the new RIA services with Silverlight 3 to insert, update and delete data.
Silverlight and RIA Services - Part II
 
Part I of this article on RIA Services demonstrated how easy it is to display data from the database. I’ll now take this one step further and show you how to insert, update and delete data using RIA Services. Before beginning you should read Part I of this article, as I’ll be using the project from it. You must also install the latest RIA Services package from Microsoft. As of writing this the July 2009 version is the latest version. You can download it from here. I recommend that you also download the accompanying PDF, which provides a lot of detail, and plenty of good code samples. Also this is using some controls from the Silverlight 3 Toolkit which can be downloaded from here.
To begin with open up the project from Part I. Right now the DomainService class, NorthwindService, only has the one method, GetCustomers. Now I want to have the full set of CRUD methods in there. For this example I am going to be using the Suppliers table, not the Customers table. The easiest way to generate your CRUD methods is to delete the NorthwindService file and add a new DomainService class. Name it NorthwindService:
 
AddNewItem
 
The Add New Domain Service Class dialog appears. Select the Suppliers object and tick the Enable Editing check box before clicking OK:
 
AddNewDomainService
 
The file is created. Instead of the one method, now you have four methods created for you:
 
C#
 
public IQueryable<Supplier> GetSuppliers()
{
return this.Context.Suppliers;
}
 
public void InsertSuppliers(Supplier suppliers)
{
this.Context.AddToSuppliers(suppliers);
}
 
public void UpdateSuppliers(Supplier currentSuppliers)
{
this.Context.AttachAsModified(currentSuppliers,
this.ChangeSet.GetOriginal(currentSuppliers));
}
 
public void DeleteSuppliers(Supplier suppliers)
{
if ((suppliers.EntityState == EntityState.Detached))
      {
            this.Context.Attach(suppliers);
}
      this.Context.DeleteObject(suppliers);
}
 
VB.NET
 
Public Function GetSuppliers() As IQueryable(Of Supplier)
Return Me.Context.Suppliers
End Function
 
Public Sub InsertSuppliers(ByVal suppliers As Supplier)
Me.Context.AddToSuppliers(suppliers)
End Sub
 
Public Sub UpdateSuppliers(ByVal currentSuppliers As Supplier)
Me.Context.AttachAsModified(currentSuppliers, Me.ChangeSet.GetOriginal(currentSuppliers))
End Sub
 
Public Sub DeleteSuppliers(ByVal suppliers As Supplier)
If (suppliers.EntityState = EntityState.Detached) Then
             Me.Context.Attach(suppliers)
End If
       Me.Context.DeleteObject(suppliers)
End Sub
 
This is all that’s required for the web application. Open up the Silverlight application. For this example all the user will see is the DataGrid control. We’ll do the inserts, updates and deletes using the DataGrid in conjunction with the RIA Services DomainDataSource control. Add the following xaml to the MainPage.xaml file:
 
<Grid x:Name="LayoutRoot">
        <riaControls:DomainDataSource QueryName="GetSuppliers"                                      
                                  AutoLoad="True"
                                  x:Name="dds">
            <riaControls:DomainDataSource.DomainContext>
                <web:NorthwindContext />
            </riaControls:DomainDataSource.DomainContext>
        </riaControls:DomainDataSource>
 
        <StackPanel Orientation="Vertical">
            <data:DataGrid x:Name="dgSupplier"
IsReadOnly="False"
ItemsSource="{Binding Data, ElementName=dds, Mode=OneWay}"
            Width="700" Height="500"
            KeyUp="dgSupplier_KeyUp"
            RowEditEnding="dgSupplier_RowEditEnding">
            </data:DataGrid>           
            <Button x:Name="btnUpdate" Content="Update"
                    IsEnabled="False" Width="100" Height="25"
                    Click="btnUpdate_Click"/>
        </StackPanel>
</Grid>
 
That’s it for the xaml! The DomainDataSource control takes care of all the heavy lifting for connecting the client to the database, and Silverlight data binding takes care of the code for displaying the data. When you need to perform general CRUD work then it’s time to write some code. 
 
To begin with I have created a property that holds a reference to the DomainDataSource’s DomainContext:
 
C#
 
private DomainContext Context
{
get
      {
      return dds.DomainContext;
      }
}
 
VB.NET
 
Private ReadOnly Property Context() As DomainContext
Get
       Return dds.DomainContext
End Get
End Property
 
Then in the constructor you need to create an event handler that is raised whenever a property has changed to a supplier entity in the DataGrid. The UpdateHasChanges main purpose is to enable/disable the button so that it is enabled when the user changes data, and disabled when they’re not:
 
C#
 
public MainPage()
{
InitializeComponent();
      Loaded += new RoutedEventHandler(MainPage_Loaded);
}       
 
void MainPage_Loaded(object sender, RoutedEventArgs e)
{    
Context.Entities.PropertyChanged += (s, o) =>
      {
            if (o.PropertyName == "HasChanges")
            {
                  UpdateHasChanges();
}
};
}
 
private void UpdateHasChanges()
{           
EntityChangeSet changes = Context.Entities.GetChanges();
      btnUpdate.IsEnabled = Context.HasChanges;
} 
 
VB.NET
 
Public Sub New()
InitializeComponent()
       AddHandler Loaded, AddressOf MainPage_Loaded
End Sub
 
Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
AddHandler Context.Entities.PropertyChanged, Function(s, o) AnonymousMethod1(s, o)
End Sub
 
Private Function AnonymousMethod1(ByVal s As Object, ByVal o As Object) As Boolean
             If o.PropertyName = "HasChanges" Then
                        UpdateHasChanges()
             End If
      Return True
End Function
 
Private Sub UpdateHasChanges()
Dim changes As EntityChangeSet = Context.Entities.GetChanges()
       btnUpdate.IsEnabled = Context.HasChanges
End Sub
 
Deleting Data
To delete data in this example, the user will hit the delete key on their keyboard. The code below shows you how to delete the selected supplier:
 
C#
 
private void dgSupplier_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete && dgSupplier.SelectedItem != null)
{
var supplier = dgSupplier.SelectedItem as Supplier;
(dds.DomainContext as NorthwindContext).Suppliers.Remove(supplier);
            UpdateHasChanges();
}
}
 
VB.NET
 
Private Sub dgSupplier_KeyUp(ByVal sender As Object, ByVal e As KeyEventArgs)
If e.Key = Key.Delete AndAlso dgSupplier.SelectedItem IsNot Nothing Then
Dim supplier = TryCast(dgSupplier.SelectedItem, Supplier)
TryCast(dds.DomainContext, NorthwindContext).Suppliers.Remove(supplier)
             UpdateHasChanges()
End If
End Sub
 
To delete the selected supplier, the record must first be removed from the list of suppliers in the RIA Service. Once that is removed, UpdateHasChanges is called to enable the update button. 
Inserting Data
To insert data it’s not as straight forward as I thought. The way to do it is not to add a new row to the DataGrid, but to add a new blank supplier and let our RIA Service update the DataGrid with the blank row. The code below shows you how to insert a new supplier:
 
C#
 
private void dgSupplier_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Insert)
      {
(dds.DomainContext as NorthwindContext).Suppliers.Add(new Supplier()
            {
                  Address = "", City = "",
                  Country = "", PostalCode = "",
                  Region = "", CompanyName = "",
                  ContactName = "", ContactTitle = "",
                  Fax = "", Phone = ""
});
            dds.SubmitChanges();
            dds.Load();
      }
}
 
VB.NET
 
Private Sub dgSupplier_KeyUp(ByVal sender As Object, ByVal e As KeyEventArgs)
If e.Key = Key.Insert Then
TryCast(dds.DomainContext, NorthwindContext).Suppliers.Add(New Supplier() With {.Address = "", .City = "", .Country = "", .PostalCode = "", .Region = "", .CompanyName = "", .ContactName = "", .ContactTitle = "", .Fax = "", .Phone = ""})
             dds.SubmitChanges()
             dds.Load()
End If
End Sub
 
The new supplier will be added to the bottom of the DataGrid. The Load method is executed on the DomainDataSource re-binds the new data to the DataGrid. The code for the update button is as follows:
 
C#
 
private void btnUpdate_Click(object sender, RoutedEventArgs e)
{           
Context.SubmitChanges(DataSaved, null);
}
 
private void DataSaved(SubmitOperation sender)
{           
}
 
VB.NET
 
Private Sub btnUpdate_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Context.SubmitChanges(AddressOf DataSaved, Nothing)
End Sub
 
Private Sub DataSaved(ByVal sender As SubmitOperation)
End Sub
 
All changes are submitted to the database via the DomainContext’s SubmitChanges method. If there are any errors during the process they will be passed back to the DataSaved function through the SubmitOperation class. Now you can add, edit and delete suppliers all from the comfort of the one control, and it’s using RIA Services. Pretty cool huh?!
 
I hope you have enjoyed reading the second part of this article. I have enjoyed writing about RIA Services and I hope you find them interesting too. They do make your life easier when it comes to Silverlight development, so start using them today!

The entire source code of this article can be downloaded over here
 
If you liked the article,  Subscribe to the RSS Feed or Subscribe Via Email

Malcolm Sheridan is an independent contractor who has been working with Microsoft technologies since VB4. Malcolm has worked with .NET since its inception and thoroughly enjoys ASP.NET.
 
Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET, a Telerik Insider and a regular presenter at conferences and user groups throughout Australia and New Zealand. Being an ASP.NET guy, his focus is on web technologies and has been for the past 10 years. He loves working with ASP.NET MVC these days and also loves getting his hands dirty with jQuery and JavaScript. He also writes technical articles on ASP.NET for SitePoint and other various websites. Follow him on twitter @malcolmsheridan


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by J Sansom on Saturday, August 22, 2009 6:09 AM
Coming as a flash developer, this article is very interesting to me. You have made me fall in love with RIA services. Great post, thanks for the info.
Comment posted by sunil on Thursday, November 12, 2009 7:41 AM
Great article, thanks very much.

Do you know if it is possible to get this example running in Out Of Browser mode.

Regards,
Sunil.
Comment posted by suleman on Tuesday, December 22, 2009 5:17 AM
Hi,
When i run the application after downloading , I am getting the following errors.
Can you please help in this regards.

Error   1   Could not load type 'System.Web.Ria.Data.ExternalAttribute' from assembly 'System.Web.DomainServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.   SilverlightApplication1

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel