Aug
30
2009
Previously,I gave an overview of the EntityCollection. In this post we are going to look at how the EntityCollection actually works and how we can add our own EntityCollections to extend our client side entities.
First, lets look at how RIA Services generates an EntityCollection during code generation
private EntityCollection<Book> _books;
[Association("Library_Book", "LibraryId", "LibraryId")]
[XmlIgnore()]
public EntityCollection<Book> Books
{
get
{
if ((this._books == null))
{
this._books = new EntityCollection<Book>(this, "Books",
this.FilterBooks, this.AttachBooks, this.DetachBooks);
}
return this._books;
}
}
private void AttachBooks(Book entity)
{
entity.Library= this;
}
private void DetachBooks(Book entity)
{
entity.Library= null;
}
private bool FilterBooks(Book entity)
{
return (entity.LibraryId == this.LibraryId);
}
Lets look at that constructor, from the documentation the constructor is defined as
public EntityCollection(
Entity parent,
string memberName,
Func<TEntity, bool> entityPredicate,
Action<TEntity> attachAction,
Action<TEntity> detachAction
)
So, the generated code is creating a new instance of EntityCollection passing in the current entity as the parent, “Books” as the name of the property, and FilterBooks as the EntityCollection’s filter.
The AttachAction and DetachAction are the actual methods (beyond some internal plumbing) that you are calling when you call EntityCollection.Add and EntityCollection.Remove. Now that you see the actual code perhaps my earlier advice on not using Detach and Attach for attached entities makes more sense.
The Fun Part
Now, here is the fun part. We can actually create our own EntityCollections. In the above example we have an collection of books. What if I want multiple collections of books each filtered by the type of book? This can easily be done using custom EntityCollections.
public sealed partial class Library
{
private EntityCollection<Book> _mysteryBooks;
[Association("Library_MysteryBook", "LibraryId", "LibraryId,Category")]
[XmlIgnore()]
public EntityCollection<Book> MysteryBooks
{
get
{
if ((this._mysteryBooks == null))
{
this._mysteryBooks = new EntityCollection<Book>(this, "Books", this.FilterMysteryBooks);
}
return this._mysteryBooks;
}
}
private bool FilterMysteryBooks(Book entity)
{
return (FilterBooks(entity) && entity.Category == "Mystery");
}
}
Here I am using the alternate constructor which doesn’t have attach and detach. In this case, I wanted my EntityCollection to be read only. I also called the original FilterBooks function in hopes that this would make future maintenance easier.
Keep in mind that EntityCollection isn’t really a CollectionView. There is no external refresh method, the EntityCollection only refreshes based on the information in the attached AssociationAttribute. That means only new Books, deleted Books, or changes to LibraryFk or Category will cause the EntityCollection to refresh.