Sep
1
2009

Meet the EntityRef and the AssociationAttribute

Today I am going to cover the EntityRef and the AssociationAttribute, but first some cleanup on the EntityCollection. In the Advanced EntityCollection post I had part of the constructor explained incorrectly, it has been corrected as well as some cleanup on the code to make it more understandable.

The EntityRef

The EntityRef is the one-to-one relationship version of the EntityCollection, which means it is probably even less well known. Like the EntityCollection, the EntityRef has two different jobs depending on if the Entity is attached to an EntityList or not. However, the EntityRef is not directly exposed by the Entity, instead it is used to back a property with the type of the associated Entity. Here is the Book Entity’s Library property, the other side of the association covered in the EntityCollection posts.

[Association("Library_Book", "LibraryId", "LibraryId", IsForeignKey=true)] 
[XmlIgnore()] 
public Library Library 
{ 
    get 
    { 
        if ((this._library == null)) 
        { 
            this._library = new EntityRef<Library>(this, "Library", this.FilterLibrary); 
        } 
        return this._library.Entity; 
    } 
    set 
    { 
        Library previous = this.Library; 
        if ((previous != value)) 
        { 
            this.ValidateProperty("Library", value); 
            if ((previous != null)) 
            { 
                this._library.Entity = null; 
                previous.Book.Remove(this); 
            } 
            this._library.Entity = value; 
            if ((value != null)) 
            { 
                value.Book.Add(this); 
                this.LibraryId = value.LibraryId; 
            } 
            else 
            { 
                this.LibraryId = default(Nullable<Guid>); 
            } 
            this.RaisePropertyChanged("Library"); 
        } 
    } 
}

private bool FilterLibrary(Library entity) 
{ 
    return (entity.LibraryId == this.LibraryId); 
}

One important thing to note if you want to create your own properties backed by an EntityRef which are not read only, the this.ValidateProperty(“Library”, value) line is actually causing the getter to be called making sure that the _library field is getting populated. If you remove that line without replacing it you may get null reference exceptions.

 

Meet the AssociationAttribute

public AssociationAttribute( 
    string name, 
    string thisKey, 
    string otherKey 
) 

Parameters
name: Name of the association
thisKey Comma separated list of the property names of the key values on this side of the association
otherKey comma separated list of the property names of the key values on the other side of the association

So, what does that pesky AssociationAttribute actually do? Both the EntityCollection and EntityRef require it but it is not obvious why that is. Also, what is the benefit of using EntityCollection and EntityRef over using a real CollectionView and a regular property?

Both the EntityCollection and EntityRef monitor an EntityList for any changes to make sure that the associations are always kept up to date. However, if the various Filter method were called every time anything changed on the entities the performance issues would quickly get out of control. For example, lets say we have 10 libraries and we are entering 20 books with each book have 15 fields that we are changing. By the time we were done we would have called the FilterBook method 3,000 times (10 libraries * 20 books * 15 fields. This is not very efficient.

To solve this problem, the EntityCollection and EntityRef only listen for changes made to those fields listed in the AssociationAttribute. This reduces us to 200 calls to FilterBook (10 libraries * 20 books * 1 field). By using the EntityRef and EntityCollection in our own code we are able to leverage this huge performance advantage ourselves. RIA Services probably has other uses for AssociationAttribute, but this is a really important one.

blog comments powered by Disqus

Month List