I have been a big fan of using the RESTful ADO.NET Data Services (aka Astoria). If you want to use Astoria out of the box without any modifications you really have to use the Entity Framework. But as long as you are using a data access library that supports IEnumerable and IQueryable (and IUpdateable to be useful for CRUD) you can use Astoria with just a little bit of extra work. 

Telerik OpenAccess supports LINQ and IUpdateable and can be used in Astoria as shown here. In a nutshell you have to first create your data access layer, then a web site to host your ADO .NET Data Service and then a client (in our case a Silverlight app.) You would have a solution that will look like this:

image

The problem is that if you use anything other than the Entity Framework, you need to do a little extra plumbing. In our case using OpenAccess, you have to create the IQueryable interfaces for all of your entities manually. You would need something like this:

 1: public IQueryable<Customer>
Customers
 2: {
 3:  get
 4:  {
 5:  return this.scope.Extent<Customer>();
 6:  }
 7: }

 

The scope variable you see on line # 5 is an instance of IObjectScope. IObjectScope is how OpenAcces implements the actual data context. According to the OpenAccess team, you have to add a few extra lines of code with these IQueryable interfaces into an “OADataContext” class. To be honest, I don’t want to do that, too much plumbing code.

Enter the OpenAccess WCF Wizard I wrote about before.

You can use the Wizard to generate the OADataContext file as well as the Astoria service file. Just point the wizard to the DAL layer file and select Astoria from the menu and generate the files and add them to the project (it is ok to overwrite the original CS file supporting the SVC file, just make sure you have the correct namespaces).

image

Now your Astoria service will look like this:

 1:  [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults
= true)]
 2:  public class WebDataService
: DataService<AstoriaDataContext>
 3:  {
 4:  protected override void HandleException(HandleExceptionArgs
args)
 5:  {
 6:  base.HandleException(args);
 7:  }
 8:  
 9:  // This method is
called only once to initialize service-wide policies.
 10:  public static void InitializeService(IDataServiceConfiguration
config)
 11:  {
 12:  //let all the entities be full
access (CRUD)
 13:  config.SetEntitySetAccessRule("*",
EntitySetRights.All);
 14:  }
 15:  }
 16: }

This is pretty standard Astoria stuff, line #13 does all of the Astoria magic.

Now let’s look at our Silverlight client.  First let’s create some XAML, I will just show you the DataGrid code here:

 1: <data:DataGrid Grid.ColumnSpan="2" x:Name="dataGridCustomers" AutoGenerateColumns="False" ItemsSource="{Binding}">
 2:  <data:DataGrid.Columns>
 3:  <data:DataGridTextColumn Binding="{Binding
Path=CompanyName}" Header="Company
Name"></data:DataGridTextColumn>
 4:  <data:DataGridTextColumn Binding="{Binding
Path=ContactName}" Header="Contact
Name"></data:DataGridTextColumn>
 5:  </data:DataGrid.Columns>
 6: </data:DataGrid>

 

As I wrote the other day, you still have to use a service and call the service asynchronously. In our Silverlight application we will then set a service reference to our Astoria Service, allowing us to write LINQ statements against the RESTful Astoria service.

image

Just like before we will have a LoadData() private method that our page load and “refresh” buttons will call. This will use LINQ to talk to the Astoria service and fetch all of the Customers. First we set up a LINQ data context (lines 4-5) and then a LINQ query (lines 8-9). Then we will use a code block (lines 13-14) to catch the async code (instead of a separate event handler) and perform the actual binding to the grid.

 1: private void LoadData()
 2: {
 3:  //this uses the
LINQ to REST proxy (WebDataService)
 4:  AstoriaDataContext dat = new AstoriaDataContext(
 5:  new Uri("WebDataService.svc",
UriKind.Relative));
 6:  
 7:  //link statement
to get the data, can use WHERE, Orderby, etc
 8:  var customers = 
 9:  (from c in dat.Customers
select c) as DataServiceQuery<WebDataService.Customer>;
 10:  
 11:  //use code block
to perform the binding at the end of the async call
 12:  //casting the Customers to
a LIST
 13:  customers.BeginExecute(
 14:  (ar) => dataGridCustomers.DataContext = customers.EndExecute(ar).ToList(), null);
 15: }

When we run our code, we will get data right away:

image

We can also perform an update. We have a global collection called editedCustomers and we trap the BeginEdit method of the Silverlight grid and put an instance of each row (a Customer) that was edited into this collection. Then we provide an update button that will call UpdateData() shown below. UpdateData() will loop through each dirty customer in the editedCustomers collection (lines 8-11) and update them using the Astoria LINQ services (lines 10-11). Inside of our loop we are doing another code block (lines 12-25) to catch the async update. We use a counter to figure out when we are done (lines 16-22), since in an async model, your 3rd update out of 5 can be the last one to finish!

 

 1: private void UpdateData()
 2: {
 3:  //this uses the
LINQ to REST proxy (WebDataService)
 4:  AstoriaDataContext dat = new AstoriaDataContext(
 5:  new Uri("WebDataService.svc",
UriKind.Relative));
 6:  
 7:  //editedCustomers
is a local collection containing only the dirty records
 8:  foreach (WebDataService.Customer
customer in editedCustomers)
 9:  {
 10:  dat.AttachTo("Customers",
customer);
 11:  dat.UpdateObject(customer);
 12:  //code block to handle the
async call to updates
 13:  dat.BeginSaveChanges(
 14:  (ar) =>
 15:  {
 16:  updatedCounter++;
 17:  //once we are finished
with all items in the collection, we are done
 18:  if (updatedCounter
== this.editedCustomers.Count)
 19:  {
 20:  MessageBox.Show("Customers
have been changed successfull!", "Saving Changes",
MessageBoxButton.OK);
 21:  this.editedCustomers.Clear();
 22:  }
 23:  
 24:  dat.EndSaveChanges(ar);
 25:  }
 26:  , null);
 27:  }
 28: }

 

That is it to build an Astoria based Silverlight application using OpenAccess. The OpenAccess WCF Wizard takes care of building the OpenAccess specific plumbing DataContext class for you as well as the Astoria service. Soon I will post another video by .NET Ninja in training Peter Bahaa on this demo as well as some more code examples using the WCF REST Toolkit and the OpenAccess WCF Wizard.

The code is available here. Enjoy!


About the Author

Steve Forte

 sits on the board of several start-ups including Triton Works. Stephen is also the Microsoft Regional Director for the NY Metro region and speaks regularly at industry conferences around the world. He has written several books on application and database development including Programming SQL Server 2008 (MS Press).

Comments

Comments are disabled in preview mode.