How to retrieve many to many (N-N) data from WCF RIA services
Can you retrieve Many-to-Many data in a Silverlight RIA Application?
Download Demo project ManyToMany.zip
This tutorial shows how to retrieve Many-to-Many data in a Silverlight RIA Application. Here is our data model:
I want to show a list of movies and each movie contains actors:
Set up your project
The following things are pretty common for a typical Silverlight Business Application:
- Create a Silverlight Application with RIA services enabled
- Create a database
- Create an ADO.NET Entity model from database
-=> BUILD THE PROJECT <=–
- Create a DomainService from the entity model
- Create a ViewModel
- Create a UI that holds a Listbox for the movies and bind it to the ViewModel
The following step is to retrieve data in the ViewModel
public MainViewModel()
{
var context=new MovieDomainContext();
var lo = context.Load<Movie>(context.GetMovieQuery());
lo.Completed += delegate
{
Movies =new ObservableCollection<Movie>( lo.Entities);
OnPropertyChanged("Movies");
};
}
The default behavior is that only the movies are retrieved. No surprises here. But how do we get the Actors?
Get more data
Open the DomainService and add a method:
public IQueryable<Movie> GetMovieWithActors()
{
return this.ObjectContext.Movie.Include("MovieActor.Actor");
}
As you can see, the syntax for the Include method is: Include(“Table1.Table2”)
Open DomainService.metadata and find the properties that should include child entities. Add an [Include] attribute to them:
internal sealed class MovieMetadata
{
// Metadata classes are not meant to be instantiated.
private MovieMetadata()
{
}
[Include] // HERE.......
public EntityCollection<MovieActor> MovieActor { get; set; }
public int MovieId { get; set; }
public string Name { get; set; }
}
internal sealed class MovieActorMetadata
{
// Metadata classes are not meant to be instantiated.
private MovieActorMetadata()
{
}
[Include] // AND HERE......
public Actor Actor { get; set; }
public int ActorId { get; set; }
public Movie Movie { get; set; }
public int MovieActorId { get; set; }
public int MovieId { get; set; }
}
Open your ViewModel and use the GetMovieWithActors query:
public MainViewModel()
{
var context=new MovieDomainContext();
var lo = context.Load<Movie>(context.GetMovieWithActorsQuery());
lo.Completed += delegate
{
Movies =new ObservableCollection<Movie>( lo.Entities);
OnPropertyChanged("Movies");
};
}
If you place a breakpoint on the OnPropertyChanged line, you can see that the Movies collection holds a list of MovieActors and each MovieActor holds an Actor entity.