DLinq O/R Mapper - EntitySet and Attach / Detach Private Methods - Parent Child Relationships
by David Hayden ( C# .NET Developer )
Filed: LINQ, O/R Mappers
A few of the other interesting decorations on the DLinq entities created by SqlMetal have to do with making sure parent / child relationships and associations are in-sync between entities.
Let's take my previous example(s):
My Movie Collection that is separated into Genres ( Action, Drama, SciFi, etc.) with each movie in the collection assigned to 1 genre. Hence we have a 1 to many relationship between Genre and Movie.
The Genre class contains a collection of movies that is represented by an EntitySet Class:
public Genre()
{
this._Movies = new EntitySet<Movie>
(new Notification<Movie>(this.attach_Movies),
new Notification<Movie>(this.detach_Movies));
}
public EntitySet<Movie> Movies
{
get
{
return this._Movies;
}
set
{
this._Movies.Assign(value);
}
}
Notice that the EntitySet<Movie> class created in the Genre Constructor is passed a couple of methods, attach_Movies and detach_Movies.
These methods are included in the Genre Class as such:
private void attach_Movies(Movie entity)
{
this.OnPropertyChanging(null);
entity.Genre = this;
this.OnPropertyChanged(null);
}
private void detach_Movies(Movie entity)
{
this.OnPropertyChanging(null);
entity.Genre = null;
this.OnPropertyChanged(null);
}
What is happening here is that everytime you add or remove a Movie to / from a Genre's Movie collection, attach_Movies and detach_Movies get called as appropriate to make sure the Movie's Genre Property is set to the proper Genre.
Hence, when you write code like this:
Genre drama = new Genre();
drama.Name = "Drama";
Movie ransom = new Movie();
ransom.Name = "Ransom";
drama.Movies.Add(ransom);
the attach_Movies event gets called upon drama.Movies.Add(ransom) which automatically under the covers makes this assigment for you:
ransom.Genre = drama;
and, of course, if you were removing a movie from the collection, the following assignment happens within detach_Movies:
ransom.Genre = null;
Now if works the other way, too. If you were to write the following code:
ransom.Genre = null;
The movie also has to be removed from a genre's movie collection class to keep things in-sync. All of this takes place in the movie's setter for Genre:
public partial class Movie ...
public Genre Genre
{
get
{
return this._Genre.Entity;
}
set
{
Genre v = this._Genre.Entity;
if ((v != value))
{
this.OnPropertyChanging("Genre");
if ((v != null))
{
this._Genre.Entity = null;
v.Movies.Remove(this);
}
this._Genre.Entity = value;
if ((value != null))
{
value.Movies.Add(this);
}
this.OnPropertyChanged("Genre");
}
}
}
Crazy, but necessary synchronization happening between the classes. Unfortunately, this stuff is being entered into our DLinq entity classes which means you need to be careful about how you write the entities. Of course, DLinq is helping you with a lot of persistence functionality, so it is a small price.
I see this being very useful for small projects, but unsure of the scalability. Still early to make any conclusions as DLinq is still in CTP.
Source: David Hayden ( C# .NET Developer )
Filed: LINQ, O/R Mappers