views:

290

answers:

3

I've been learning by doing with ADO.Net Data Services (Astoria) for the last couple of months, and while I like the technology the learning has been a real trial. Information that you need to use them effectively is spread over MSDN documentation, articles, blog posts, support forums and of course StackOverflow. This question is a place for me to share some of my hard-won findings so that someone else can benefit. I also hope for other people to contribute their best practices and FAQs, and correct my misunderstandings!

For full disclosure, I've been using the framework with Linq to SQL just to make my life more complicated, so I hope the details in my answers are appropriate for Entity Framework too.

To start with below are some links I've found essential. I'll then put topic specific bits in the answers section.

Useful Links

+1  A: 

Silverlight Client Library

LINQ Querying

At first it looks like the linq syntax can't be used from your context, because all queries are asynchronous and IEnumerable obviously doesn't have a BeginExecute method. To use the Linq syntax you need to cast your eventual query:

var query = (DataServiceQuery<Product>)myContext.Products.Where(p => p.SupplierID == 5);
query.BeginExecute(this.HandleQueryResults, query);

Note the query is passed in, this is because you'll need to use the same DataServiceQuery instance to call EndExecute, you can't just use the context.

Change Tracking

The client library doesn't track field changes automatically in the generated types. For this to work you must implement INotifyPropertyChanged in your partial types.

Example:

public partial class Product : INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    partial void OnProductIDChanged() { FirePropertyChanged("ProductID"); }
    partial void OnProductNameChanged() { FirePropertyChanged("ProductName"); }

    private void FirePropertyChanged(string property) { ... }
}

In version 1.5 the Data Services tooling can generate this for you, but it's currently only in CTP: Introduction to Data Binding in Silverlight 3 with 1.5 CTP2

Updated Server Data

By default the Silverlight client context has MergeOption set to AppendOnly. What this means is that you won't see any changes to entities once you've queried them for the first time, it's a form of caching and performance optimization. To see updates you need to change the MergeOption to OverwriteChanges, this will ensure the objects are updated. You can also throw away your context and re-create.

myContext.MergeOption = MergeOption.OverwriteChanges

Cross Domain Access

The Silverlight generated types for ADO.NET Data Services 1 use their own network stack to make more request verbs available, but unfortunately this means that the cross-domain policies are not applied and you can't make cross-domain requests. To work around this you can either proxy the requests or wait for version 1.5 (CTP 2 currently available) which supports cross-domain in Silverlight 3.

Links:

Simon Steele
+1  A: 

Working with Linq to SQL

You can use Linq to SQL as a read-only data context for Data Services right out of the box:

public class MyService : DataService<MyLinqToSqlDataContext>

To get update/write support, however, you'll need to have an implementation of IUpdateable for Linq to SQL. Fortunately Andrew Conrad has one up on the MSDN Code Gallery for you:

ADO.Net Data Services IUpdateable implementation for Linq to Sql

Drop this in as a partial class for your data context and you are ready to write as well as read. Do note that this implementation does have a few minor issues detailed on the site, and that sometimes using Data Services with Entity Framework as designed feels a little more seamless.

Update Checks

When storing changes you'll see that Linq to Sql generates a WHERE clause that checks the existing values on fields, which isn't always what you want. This is really a Linq to Sql tip rather than Data Services specific, but this is the only place I use Linq to Sql. To stop this behaviour go into the Linq to Sql designer and select the fields you don't want to check. Change the UpdateCheck property to Never or OnlyWhenChanged.

Simon Steele
+2  A: 

Service Operations

Sometimes being able to query data and perform simple updates or creations isn't enough - you might want to implement some business logic or some complex query creation that's not possible through the URI scheme. Data Services supports this in a very basic form with Service Operations.

These allow you to add methods to your service, but with some restrictions:

  1. You can only use basic types or entity types (i.e. types already exposed by the service).
  2. Method parameters can only be simple types that can be expressed as part of a URL.
  3. No code is generated for Service Operations by datasvcutil, so you need to add them to the client libraries yourself.
  4. If you return a entity type but don't have anything to return, i.e. the result is null, then you'll get a 404 as the HTTP response.
  5. If you return void you won't be able to use the client data context to make the request, you'll have to use WebRequest.

Examples (ok, these are simplified so don't really need to be Service Operations):

[WebGet]
public Product GetProductByID(int productID)
{
    return this.CurrentDataSource.Products.First(p => p.ID == productID);
}

[WebGet]
public IEnumerable<Product> GetCancelledProducts(int productID)
{
    return this.CurrentDataSource.Products.Where(p.Cancelled);
}
Simon Steele
These should all be community wiki, as should the question.
Adam Robinson