Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C# 4.0
Tip/Trick

Async OData

Rate me:
Please Sign up or sign in to vote.
4.90/5 (3 votes)
7 Sep 2012CPOL1 min read 20.8K   6   4
Show how to make OData code async friendly

Introduction

In this short tip, I explain how I made an OData sample using the async extension of .NET 4.5.

Using the Code

Today, I watched this video about using OData in a WinRT app.

To summarize, he (Jerry Nixon) adds a service reference to the Netflix OData API at http://odata.netflix.com/ and then proceeds to do something like:

C#
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var _uri = new Uri("http://odata.netflix.com/Catalog/");
    var ctxt = new NetFlixService.NetflixCatalog(_uri);
    var data = new DataServiceCollection<NetFlixService.Title>(ctxt);
    var query = from t in ctxt.Titles
                where t.Name.Contains("Star Trek")
                select t;
    data.LoadCompleted += delegate 
    {
        this.DataContext = data;
    };
    data.LoadAsync(query);
}

Basically, he creates an OData service reference, runs a database query against it, and shows the results.

What I will show is how to improve this, how to use the new async / await keywords instead of the LoadCompleted delegate.

There seems to be no obvious way of doing that! Time to Google!

From the await (C# Reference) reference, it seems that await can (only) be applied to a method returning a Task, and a Task (from Googling) can be created from IAsyncResult.

So first, I started by creating a very simple and reusable IAsyncResult implementation class:

C#
public class SimpleAsyncResult : IAsyncResult, IDisposable
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    public void Finish()
    {
        IsCompleted = true;
        waitHandle.Set();
        waitHandle.Dispose();
    }
    public void Dispose() { waitHandle.Dispose(); }  

    public bool IsCompleted { get; private set; }
    public object AsyncState { get; set; }
    public bool CompletedSynchronously { get; set; }
    public WaitHandle AsyncWaitHandle { get { return waitHandle; } }
}

With that, I can easily create an extension method for my OData classes returning a Task:

C#
public static class OData
{
    public static Task<DataServiceCollection<T>> AsyncQuery<T>(
           this DataServiceCollection<T> data, IQueryable<T> query = null)
    {
        var asyncr = new SimpleAsyncResult();
        Exception exResult = null;
        data.LoadCompleted += delegate(object sender, LoadCompletedEventArgs e)
        {
            exResult = e.Error;
            asyncr.Finish();
        };
        if (query == null)
            data.LoadAsync();
        else
            data.LoadAsync(query);
        return Task<DataServiceCollection<T>>.Factory.FromAsync(asyncr
            , r =>
            {
                if (exResult != null)
                    throw new AggregateException("Async call problem", exResult);
                return data;
            }
        );
    }
}

Remark: Here, I wrap the exception because I don’t want to lose the stack trace (with “throw exResult”).

And voila, I can update my NavigatedTo method to use the .NET4.5 async extension!

C#
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    var _uri = new Uri("http://odata.netflix.com/Catalog/");
    var ctxt = new NetFlixService.NetflixCatalog(_uri);
    var data = new DataServiceCollection<NetFlixService.Title>(ctxt);

    var query = from t in ctxt.Titles
                where t.Name.Contains("Star Trek")
                select t;
    await data.AsyncQuery(query);
    this.DataContext = data; 
} 

Points of Interest

This is a nice way to explore some internals of the async extension in .NET4.5.

History

  • 1.0: First version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) http://www.ansibleww.com.au
Australia Australia
The Australia born French man who went back to Australia later in life...
Finally got over life long (and mostly hopeless usually, yay!) chronic sicknesses.
Worked in Sydney, Brisbane, Darwin, Billinudgel, Darwin and Melbourne.

Comments and Discussions

 
Questionsource code Pin
kiquenet.com18-Jan-13 2:08
professionalkiquenet.com18-Jan-13 2:08 
AnswerRe: source code Pin
Super Lloyd19-Jan-13 15:25
Super Lloyd19-Jan-13 15:25 
QuestionUse this extension method instead Pin
Jerry Nixon2-Oct-12 5:27
Jerry Nixon2-Oct-12 5:27 
AnswerRe: Use this extension method instead Pin
Super Lloyd4-Oct-12 0:42
Super Lloyd4-Oct-12 0:42 
Hey, it's you!! Smile | :)
Nice tips, thanks!
A train station is where the train stops. A bus station is where the bus stops. On my desk, I have a work station....
_________________________________________________________
My programs never have bugs, they just develop random features.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.