Click here to Skip to main content
Click here to Skip to main content

Async OData

By , 7 Sep 2012
 

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: http://blog.jerrynixon.com/2012/08/new-episode-devradio-let-odata-make.html.

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

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 how to improve this, is 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:

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:

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!

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)

About the Author

Super Lloyd
Software Developer (Senior) http://www.zerocorporation.com/
Australia Australia
Member
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.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionsource codememberkiquenet.com18 Jan '13 - 2:08 
it's great!
 
any full source code sample about it?
kiquenet.com

AnswerRe: source codememberSuper Lloyd19 Jan '13 - 15:25 
Thanks!
Mm.. just browse through my hard disk.. I don't seem to have it!
At any rate, the video is only about 10 minutes!
And the code is all typed manually, there is little of it!
Common, you can do it too! 8-0
My programming get away... The Blog...
Taking over the world since 1371!

QuestionUse this extension method insteadmemberJerry Nixon2 Oct '12 - 5:27 
Nice article.
 
So, more simply - to do this:
 
 
    var _Query = _Context.Titles
        .Where(x => x.name.Contains('Star Trek'));
    var _Results = await _Query.ExecuteAsync();
 
 
Here's the extension method you use:
 
 
    public static async Task<IEnumerable<T>> ExecuteAsync<T>(this DataServiceQuery<T> query)
    {
        return await Task.Factory
            .FromAsync<IEnumerable<T>>(query.BeginExecute(null, null), query.EndExecute);
    }
 

AnswerRe: Use this extension method insteadmemberSuper 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    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 7 Sep 2012
Article Copyright 2012 by Super Lloyd
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid