(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Working with collections in WCF RIA Services (part 1)

(7 votes)
Kevin Dockx
>
Kevin Dockx
Joined Nov 15, 2010
Articles:   19
Comments:   8
More Articles
7 comments   /   posted on May 10, 2011
Categories:   Data Access , Line-of-Business

This is the first part of a two-part series on working with collections in WCF RIA Services.

Introduction

A lot of business applications today are built with WCF RIA Services (which should come as no surprise, as it’s a really powerful, extensible framework).  However, the collection type support could have been better. Often, you’d simply resort to fetching your entities and adding them to an ObservableCollection<T> in the completed event of your load operation. This still works, but in the first Service Pack for WCF RIA Services quite a few enhancements to existing collection types have been made, and new ones have been added. These allow you to make it easier to work with WCF RIA Services in an MVVM context: we now have collections which automatically track your DomainContext, collections which allow you to add filters, sorting & even grouping, and there’s a server-side pageable DomainCollectionView. In this article, we’ll have a look at these enhancements & new types, and the scenarios in which they can prove useful.

This article will look into 4 ways of working with your data from WCF RIA Services: the EntitySet (enhanced), the EntityList (new), the CollectionView (enhanced) and last but not least, the DomainCollectionView (new). It is accompanied by an example project & full source code, which you can download here.

SP1 for WCF RIA Services is included in Visual Studio 2010 SP1, which can be found here.

EntitySet<T>

The EntitySet is a basic collection type you can use in your WCF RIA Services application, for binding from your ViewModel. It’s an unordered collection with few options for customizing what it returns, but therefore it’s a simple, quick and easy solution if you need to view all the entities of a specific type which have been loaded through your DomainContext.

In the example application, I’m binding a ListBox to a property, Books:

image

Have a look at the following code:

/// <summary>
/// The Books property
/// </summary>
public EntitySet<Book> Books
{
    get
    {
        return Context.Books;
    }
}

As you can see, Books is an EntitySet of type Book, and simply refers to Context.Books, of which 10 are loaded in the constructor:

public EntitySetViewModel()
{
    InstantiateCommands();
    // load books
    Context.Load<Book>(Context.GetBooksQuery().Take(10));
}

When we load more data, as such:

LoadMoreBooks = new RelayCommand(() => 
{
   Context.Load<Book>(Context.GetBooksQuery());
});

more entities of type Book are added to the correct EntitySet: Context.Books, resulting in more Books in our ListBox. In other words: when data of type Book is loaded by the DomainContext, it’s added to the Context.Books EntitySet.

EntitySet<T>: adding and removing data.

How do you add or remove data from an EntitySet? Have a look at the following code for adding a Book:

AddBook = new RelayCommand(() =>
{
    Context.Books.Add(new Book() { 
        Author = "Kevin Dockx"
        , ASIN = "123456"
        , Title = "Dummy book" });
});

and the following code for removing a Book:

DeleteBook = new RelayCommand(() =>
{
    Context.Books.Remove(Context.Books.FirstOrDefault());
});

This will result in Books being added or removed from the Books EntitySet, which is immediately visible in our ListBox. When you submit the changes to the server, this will result in the corresponding Insert / Delete operations being executed on our DomainService.

 

EnityList<T>

The next collection type we’re looking into is a new one: the EntityList<T>. It can be found in the WCF RIA Services Toolkit, in Microsoft.Windows.Data.DomainServices (assembly is included in the example code, you don’t need to download the toolkit if you don’t want to). In essence, it is an observable collection which is backed by an Entity Set. The advantage of this, and reason why you might want to use it, is that this allows us to get a view of a subset of entities of a specific type, loaded through your DomainContext into the backing Entity Set. A typical EntityList<T> property definition looks as such:

private EntityList<Book> _books;
public EntityList<Book> Books
{
    get
    {
        if (this._books == null)
        {
            this._books = new EntityList<Book>(
              this.Context.Books);
        }
        return this._books;
    }
}

An Entity List has a Source property, which defines the entities it should contain:

public EntityListViewModel()
{
    InstantiateCommands();
    // load books
    this.Books.Source = Context.Load<Book>(Context.GetBooksQuery().Take(10)).Entities;
}

With these two pieces of code, your Entity List is initialized & ready to be used. 

It gets interesting once you start loading more entities of type Book: these are NOT automatically reflected in our Entity List.  This is by design: the same subset you initialized it with is used (which is exactly what allows us to get a view on a part of the books loaded in the Entity Set via the Domain Context instead of all of them). If you want to get your Entity List to track more books, you should set the Source property of the list again:

LoadMoreBooks = new RelayCommand(() =>
{
    this.Books.Source = Context.Load<Book>(Context.GetBooksQuery()).Entities;
});

 

EntityList<T>: adding and removing data.

Adding a new entity of type Book is typically done in one of two ways: you can either add it to the Context, or add it to the Entity List itself. This results in different behavior, which you can view in the example application. When the following code is executed:

AddBook = new RelayCommand(() =>
{
    Context.Books.Add(new Book() { 
        Author = "Kevin Dockx"
        , ASIN = "123456"
        , Title = "Dummy book" });
});

a new Book is added to the Context. But as the Entity List does not automatically track this (remember: the subset of items tracked is what’s set on the Source property, not every book loaded in the context), our ListBox still only shows the entities in the Entity Lists’ Source collection.

When the following code is executed:

AddBookToEntityList = new RelayCommand(() =>
{
    Books.Add(new Book() { 
        Author = "Kevin Dockx"
        , ASIN = "123456"
        , Title = "Dummy book" });
});

A new book is added to the Entity List (Books) itself, and this is reflected in our ListBox. Behind the screens, this book is added to the backing Entity Set if it didn’t exist yet. If it was already available in the backing Entity Set, it isn’t added to the set, it’s just added to our Entity List. Submitting your changes to the server will result in the correct Insert method being executed.

Removing a Book behaves a bit different: when you remove the Book from the backing Entity Set on the Context, this is reflected in the Entity List:

DeleteBook = new RelayCommand(() =>
{
    Context.Books.Remove(Context.Books.FirstOrDefault());
});

When you remove a Book from the Entity List, this Book is also removed from the backing Entity Set, meaning a submit operation will result in the correct Delete method being called.

DeleteBookFromEntityList = new RelayCommand(() =>
{
    Books.Remove(Books.FirstOrDefault());
});

 

This concludes part one – stay tuned for part two, which will cover the more advanced collection types: the ICollectionView & DomainCollectionView.

About the author

Kevin Dockx lives in Belgium and works at RealDolmen, one of Belgium's biggest ICT companies, where he is a technical specialist/project leader on .NET web applications, mainly Silverlight, and a solution manager for Rich Applications (Silverlight, Windows Phone 7 Series, WPF, Surface). His main focus lies on all things Silverlight, but he still keeps an eye on the new developments concerning other products from the Microsoft .NET (Web) Stack. As a Silverlight enthusiast, he's a regular speaker on various national and international events, like Microsoft DevDays in The Netherlands, Microsoft Techdays in Portugal and Belgium, or on BESUG events (the Belgian Silverlight User Group). Next to that, he also authored a best-selling Silverlight book, Packt Publishing's Silverlight 4 Data and Services Cookbook, together with Gill Cleeren. His blog, which contains various tidbits on Silverlight, .NET, and the occasional rambling, can be found at http://blog.kevindockx.com/, and of course he can also be found on Twitter @KevinDockx


Subscribe

Comments

  • -_-

    RE: Working with collections in WCF RIA Services (part 1)


    posted by Teun on May 10, 2011 13:31

    Hi Kevin,

    have you tried using the DomainCollectionView source for the DataForm? Because I get exceptions if the DCV is sorted when adding a new item.

    Do you maybe know a work around?

    Greetings,
    Teun

  • KevinDockx

    RE: Working with collections in WCF RIA Services (part 1)


    posted by KevinDockx on May 10, 2011 13:56

    Hello Teun,


    I don't work with the DataForm (not too fond of that control...), but one thing you might want to look into: the DCV is in essence a view which works on servers-side data, which implies adding data should be done on the server (eg: to the context & submit changes) after which the DCV can be refreshed/reloaded.  Adding/removing data on the client on the DCV itself will typically result in unexpected behaviour, as it's not supposed to work like that. IMO, the DCV should even block an action like that, but at the moment it's still allowed (yet unusable).

    Hope this helps!

  • -_-

    RE: Working with collections in WCF RIA Services (part 1)


    posted by Teun on May 10, 2011 13:59

    Hi Kevin,

    have you tried using the DomainCollectionView source for the DataForm? Because I get exceptions if the DCV is sorted when adding a new item.

    Do you maybe know a work around?

    Greetings,
    Teun

  • -_-

    RE: Working with collections in WCF RIA Services (part 1)


    posted by Teun on May 10, 2011 14:12

    Hi Kevin,

    Thank you for your quick reply. I tried adding a new item to the DomainContext, instead of the EntityList the DCV used as source, but that did not work either. I will try other ways.

    After using the DataForm I still like the possibilities of it, but not the control itself.

    Greetings,
    Teun

    Ps. sorry about the repost of the question.

  • weitzhandler

    RE: Working with collections in WCF RIA Services (part 1)


    posted by weitzhandler on May 10, 2011 14:41
    I haven't found the EntityList<TEntity> but rather found the EntityCollection<TEntity>.
    What's the differences, have I missed something?
  • KevinDockx

    RE: Working with collections in WCF RIA Services (part 1)


    posted by KevinDockx on May 10, 2011 15:12

    Hello weitzhandler, you can find the EntityList in the WCF RIA Services Toolkit, in Microsoft.Windows.Data.DomainServices.  The assembly is included in the example solution (if you do not want to download the complete toolkit).

  • -_-

    RE: Working with collections in WCF RIA Services (part 1)


    posted by almostEric on May 11, 2011 00:54
    I enjoy WCF RIA Services for the most part, but it is pretty stunning that many-to-many relationship support is so lacking.

Add Comment

Login to comment:
  *      *       

From this series