Corey Gaudin

.NET Framework 3.5 Development and Architecture Designs
“The Next Web aka Web 3.0” and Silverlight's importance to it.
The next "Version" of the web?

I have recently been having some debates on Silverlight / AIRs importance to the web. Some of these people in the discussion often say that AJAX enabled web sites are enough for what you need on the web. I whole heartedly disagree with this assessment, so I thought I would make a blog posting about why I feel the importance of RIA development on the web is an important next step for our view of the web in the coming years.


Recently, I would say the past 5 or so years, we have been hearing a trendy word passed around called “Web 2.0”. To me, this merely means socializing on the Web in new and exciting ways. Sites such as Digg, Twitter, etc. have crafted a new age of our society and new ways for us to communicate. This is a great step forward for our generation. However, many have started to wonder what the next version of the Web will look like (“Web 3.0”).

 
I have a hypothesis of what will be more important to our next version of the web, and it will be somewhat seamless to the typical user that surfs the web. It will be a better organization of the domain layer, meaning, it will be spreading out your business logic and domain layer across multiple web services and Restful services that can allow for multiple consumption of the users data. This will allow you to access the data through Desktop application, Web applications, or consumption from other companies trying to tie into your data. Now, from this definition, there are a lot of people who are already there: Amazon, Ebay, Microsoft, etc. This is true, but once this becomes the norm way of creating content on the web, I think it will be an expected feature across all applications. To me the idea of “the next web version” will be the multiple ways of getting to your data and consuming that data.

 

Where does RIA come into this
All that being said, how does Silverlight and AIR play into this. There is an excellent article I read from nikhilk.net that talks about this: "http://www.nikhilk.net/Entry.aspx?id=190". In it he describes the Reach vs Capabilities approach, where Classic Simple HTML is the broader reach, then AJAX apps, then AJAX + RIA (Silverlight and AIR), RIA apps, then Desktop apps that finally goes to greater capability. I think this is an accurate assessment of the technology at hand.

 
To me, Silverlight (and AIR) will be the new way to present web controls and feature components that give some depth and control to the user, in a presentation that has both speed and power. Silverlight gives the same flexibility as a windows application where the separation of concerns (domain objects) rests on your web services. It helps you really build out an enterprise system that will force you to create the idea of the “next generation of the web”. It will do this by really making you think how to structure your domain objects in interesting ways. This will enable you to create your domain layer mechanisms so that they can be consumed in multiple ways, such as an AJAX Website, Desktop application, and the RIA application (Silverlight and AIR). During this process, it will allow you to space out your business logic and domain logic across multiple servers, but still provide a very quick interface for the client, as well as maintain state storage locally and give the user a better environment to manipulate their data.

 

It's not Active-X
One thing I keep hearing is Silverlight is the next Active-X. It is really nothing like Active-X, except for the fact that it runs on the client side. Active-X was a way for the client to consume a dll created by the site and run that business logic locally to that client. Silverlight is a complete framework that runs on the client’s side. The domain layer “should be” created and utilized from the Server side (web services / Rest ful APIs). The point here is that Active-X can be any user created DLL that is registered to your browser and interacts with your OS. Silverlight is the partial .NET Framework running on your system, it doesn’t interfere with the OS or register any components to it. It is completely self contained, unlike Active-X. An active-x object could wreak havoc on your system, where-as a Silverlight application has restrictions on what it can do, because it is self contained in the Framework for it.  It is nothing more or less than Flash, which is not considered Active-X in nature. What it is, is a fraction of the .NET 3.5 Framework running locally on the client, with a WPF/E (Windows Presentation Foundation Everywhere) front-end that provides vector style graphics and a rich GUI and mechanisms to consume data in multiple facets.

 

Whoa ... dont get carried away!
All that being said, I do not think having a majority of your website in Silverlight is a good thing; far from it. Silverlight, to me, is great for doing complex User controls and Components that require speed, complex GUI, depth, and simplicity of use. I can foresee a lot of Admin Sections being in Silverlight, as well as key complex components, such as Events Calendar, Attendance components, Form Builder, etc. Really anything that requires a complex GUI that requires simplicity and depth.

 
We all know that JavaScript is great for simple things, but the more complex a page gets and the more complex the GUI needs to perform, the more of a headache JavaScript can become for the typical developer. Not to mention, JavaScript will result in a much slower interface. Looking back at all of the issues I have ran into lately with several projects, over 35-40% of the issues was trying to get Javascript and .NET to play nicely together. Now, if I had been using ASP.NET MVC, a lot of those problems could have been mitigated, however, the more complex your JavaScript code is, the more cumbersome the code will get, and the more difficult to maintain. I am not saying JavaScript is bad and convoluted, but it is something to me that should be mitigated to making simple features seem more alive. 

 

Proof of concept
I am working on a proof of concept application that is built on the ASP.NET MVC framework, that makes and includes a User Control written in Silverlight (which is developed to use the same MVC pattern), to complement and see how all the pieces fit together. I read an article at http://marlongrech.wordpress.com/2008/03/20/more-than-just-mvc-for-wpf/ by Marlon, that I am very fascinated to try out in Silverlight. The article talks about using the MVC + Mediator pattern to communicate between all of the pieces in WPF. However, since Silverlight is a subset of WPF, and I cannot find a way to do the EventManger and register events of a XAML view from another class at the moment, I am having to do a mix between MVC + M and a little more work on the view’s side to create events that the controller can consume. I am trying to do as little code as possible on the Views side and keep it all confined in the Controller side. It is coming along great, and I really think this is the way to bring MVC in Silverlight with ASP.NET MVC Framework to keep the separation consistent on both sides.

 
I am currently trying to write a lot of domain base classes and interfaces to help speed up the connection of these two technologies, to help mitigate the time spent including them in the same project. I am also working on a "drag in and work" Security ASP Membership feature for MVC ASP.NET by extending a starter kit found at http://www.squaredroot.com/post/2008/04/MVC-Membership-Starter-Kit.aspx by Troy to fit the needs that I typically use for the Memberships.


I think this is an important topic for all developers and managers to address. I believe this is what the future of the web will look like, come hell or high water. You will either be on the train, or trying to flag it down. Either way, it will be a wonderful ride.


Everyone likes examples

Before I leave off today, I would like to leave some links to some good Silverlight Examples:

Quick Silverlight Examples:

MSPaint Type Example:            http://silverlight.net/Samples/2b1/ImageSnipper/testpage.html

Awesome Weather Tool:            http://silverlight.r2musings.com/weatherwidget/default.aspx

Google with a stylus or mouse:   http://www.tabletpcpost.com/search/

Upload Tool:                             http://fluxtools.net/emailphotos/

Slide show Image App:              http://www.vertigo.com/SlideShow.aspx.

 

some more neat ones at silverlight.net

 

 

 

 

 

 

.NET Developers Heaven: Mix 08 Information Overload!

As a .NET developer, I am sure most of you have been keeping up with this years Mix '08. There are tons of information that has been presented this year, and not least of which is Internet Explorer 8 Beta 1, ASP.NET's MVC Framework Preview 2Silverlight 2 Beta 1, and so on.

ASP.NET MVC Framework and Silverlight 2 has me the most excited out of everything else presented. I have not reviewed all of the session so far, however, I am in the process of soaking in all of the presentations, sessions, articles, etc. that is on these topics alone. However, I am also trying to organize where all of this wealth of knowledge is located. As a blogger, I figured many others are like me, and want a quick easy way to access all of this information quickly, without having to dig it all up on their own. So I, being the nice guy that I am, have compiled all that I have found so far (and will continue to update it with new things) into one nice neat blog article, for your convenience. If anyone has anymore links to add, please send a comment and I will be sure to update this blog post.

Once I have soaked in all of the technology information overload, I will present several blog articles specifically for Silverlight 2 and ASP.NET MVC Preview 2. Please keep in mind that there is over 2x more information on Silverlight 2.0 beta than there is for ASP.NET MVC Preview 2 (since preview 2 isn't as drastically different from preview 1 as Silverlight 2.0 beta is from Silverlight 1.0).

Without further delay, here are the direct links to the information I have found interesting so far:

ASP.NET MVC Preview 2

Mix 08 Sessions Direct Links


ASP.NET MVC Preview 2 Videos

Interesting Articles on MVC Preview 2


Interesting Articles on MVC Preview 1

MVC Source Code Examples

Resources


Silverlight 2 Beta 1 Links:


Mix 08 Sessions Direct Links


Silverlight 2.0 Tutorials


Resources

Tips and Tricks: Forcing LINQ to SQL to load Child Objects without deferred execution and why


Today I would like to discuss how to force LINQ to SQL to load child objects, as well as shape its load, without deferred execution.  Before we begin, let’s first discuss why that is even necessary.

What does Deferred execution give us:

Composable queries and deferred execution work together to make LINQ a unusual rich query language. If you properly understand these features of LINQ you will be able to write less code that executes faster, in order to accomplish more.

What problems can it create:

var query = from customer in db.Customers
            where customer.City == "Paris"
            select customer;

foreach (var Customer in query)  << Query Executes Customer here

{

Console.WriteLine(Customer.CompanyName);
foreach (var order in Customer.Orders)  << Query of Orders Executes here for each loop

{

  Console.WriteLine(order.OrderID);

}

}

As you can see above, you are sending SQL across the wire each time you loop through the Customer object. This is not an ideal way to handle this load if you already know you will need to pre-load all of the child objects ahead of time.


Forcing it to load up the child objects if you know you are going to need them:

//Create a new Data Context to load data objects
NorthwindDataContext nwind = new NorthwindDataContext();

 

//Create a DataLoad Options object to tell the Datacontext
//    how to load this object, if it
//    loads the specified object (through the generic part)

DataLoadOptions options = new DataLoadOptions();

options.LoadWith<Product>(p => p.Category);
options.LoadWith<Product>(p => p.Order_Details);
options.LoadWith<Order_Detail>(od => od.Order);

//Set the load options for this dataContext
nwind.LoadOptions = options;

 

//This products object has preloaded the Parent object Category
//    and Child object OrderDetails,
//    as well as each OrderDetails parent Order object

IEnumerable<Product> products = nwind.Products.ToList<Product>();


Changing what data actually gets loaded for the child objects for the Customer’s Order:

//Create a DataLoad Options object to tell the Datacontext
//    how to load this object, if it
//    loads the specified object (through the generic part)

DataLoadOptions newOptions = new DataLoadOptions();

 

//This will tell the Datacontext to load the Order Object
//    for the Customer (when it loads through deferred or not)
//    to load only those Orders with OrderID < 10,700 and
//    in descending order by OrderDate

newOptions.AssociateWith<Customer>(c => from o in c.Orders
                                        where o.OrderID < 10700
                                   
    orderby o.OrderDate descending
                                   
    select o);


As I hope you can see, LINQ to SQL gives you a lot of flexibility on how to load and when to load. I really do enjoy working with LINQ and all its pieces. I still have a lot to learn with it, but the more I use it the more I appreciate it and become reliant on it.



kick it on DotNetKicks.com
Detailed Look: Key components in LINQ to SQL and their Key Roles

As part of this blog, I plan to have an on-going set of articles that takes a detailed look into some part of the .NET Framework. I plan to bring as much knowledge as I can find on the topic, but drill down into a subset of its components, to make aware and have discussions. This will bring about more understanding for me and the .NET Community. So if you have suggestions, comments, or a different idea on the subject, please share it.

Before I begin on discussing its key components, I would like to point you to some very good articles written about LINQ to SQL, which should be read to have a deeper understanding of this new technology, and prepare you to be able to use it comfortably. This is a brief listing of articles written to help you better understand how to use LINQ to SQL:

Scott Gu’s Multi-part Tutorials:


Rick Strahl has many articles written on practical usages of LINQ


Pro LINQ by Joseph C. Rattz, Jr. (a book I have read cover to cover multiple times and actually reference some of his explanations).


Today I would like to discuss some of LINQ to SQL’s key components, specifically the DataContext and Entity objects. I have read a lot of articles dealing on how to effectively use LINQ to SQL, and how to structure it. However, I would like to drill down more into what two very specific parts are and what they are responsible for. Understanding these objects more fully and being aware of it, will help bring about understanding and correct usage of these components.

Before we drill down into what the DataContext and Entity objects are and what they are responsible for, let’s take a brief look at the key difference between LINQ to SQL and LINQ to Objects / XML.

What are the key differences between LINQ to SQL and LINQ to Objects / XML?

  • LINQ to SQL needs a Data Context object (generic or a Custom Inherited version).

  • LINQ to SQL returns IQueryable<T>
    LINQ to Objects / XML returns IEnumerable<T>

  • Normal LINQ queries are performed on arrays/collections that implement IEnumerable<T>.

  • LINQ to SQL queries are performed on classes that implement the TQueryable<T> interface, such as Table<T>.

  • LINQ to SQL is translated to SQL unlike LINQ to Objects / XML which are translated to Intermediate Language (IL).

    LINQ to SQL is translated to SQL by way of Expression Trees, which allow them to be evaluated as a single unit and translated to appropriate and optimal SQL Statements.

  • Normal LINQ is executed in local machine memory, LINQ to SQL is translated to SQL calls and executed on the specified Database.

What are the similarities shared between LINQ to SQL and LINQ to Objects / XML?

The similarities shared between all aspects of LINQ are the concept of Deferred Loading and Execution. I will not go into detail on this topic here, as it has been discussed countless times on various other blog articles. Suffice it to say, that it allows you define a LINQ query that maintains what you want to query, but doesn’t actually query that item until you use it.

Quick Example:

var query = from customer in db.Customers
            where customer.City == "Paris"
            select customer;

foreach (var Customer in query)  << Query Executes Customer here
{

Console.WriteLine(Customer.CompanyName);
foreach (var order in Customer.Orders)  << Query of Orders Executes here

{

  Console.WriteLine(order.OrderID);

}

}


This allows you to define what you query, through various code paths, until you actually need to use the query for data.


Example:

NorthwindDataContext northwind = new NorthwindDataContext();

var products = from p in northwind.Products
               select p;

if (somecondition)
    products = from p in products
                  where p.Discontinued
                  select p;
}

foreach (Product p in products)
{   // do something }


Responsibilities of the Entity Classes and the DataContext Class

Let us continue on to our discussion about what the DataContext and Entity objects responsibilities are and what they actually do for us. We will discuss the core concepts of what the DataContext and the Entity classes do and a description of how it does it. For the Entity class part, we will actually get down and dirty with how it actually accomplishes its responsibilities, since we can visibly see how it does it via the code generated for us.

Please note, that all of this is automatically handled if you use the SQLMetal or OR/M designer in Visual Studio 2008. This knowledge is to understand what it automatically provided to us, to better understand these objects and also if we decided to implement these features ourselves.


DataContext class is responsible for identity tracking, change tracking, and change processing. All of this is automatically handled by the base DataContext Class.

Identity Tracking:

When a record is queried from the database for the first time since the instantiation of the DataContext object, that record is recorded in an identity table using its primary key, and an entity object is created and stored in cache. Subsequent queries that determine that the same record should be returned will check the identity table, and if the record exists in the identity table, the already existing entity object will be returned from the cache. This is an important concept to grasp, so I will reiterate it in a slightly different way. When a query is executed, if a record in the database matches the search criteria, and its entity object is already cached, the already cached entity object is returned. This means that the actual data returned by the query may not be the same as the record in the database. The query determines which entities will be returned based on the data in the database, but the DataContext’s identity tracking service determines WHAT data is returned. Lucky for us, we can refresh the DataContext’s cache and have it retain our changes. I will show an example of this later.

Change Tracking:

Once the identity tracking service creates an entity object in its cache, change tracking begins for that object. Change tracking works by storing the original values of an entity object. Change tracking for an entity object continues until you call the SubmitChanges method. Calling the SubmitChanges method causes the entity objects’ changes to be saved to the database, the original values to be forgotten and the changed values to become the original values. This allows the change tracking to start over. This works fine as long as the entity objects are retrieved from the database. However, merely creating a new entity object by instantiating it will not provide any identity or change tracking until the DataContext is aware of its existence. To make the DataContext aware, simply insert the entity object into one of the Table<T> properties (that represents the collection of the Table). To accomplish this just call InsertOnSubmit or Attach method on the DataContext’s Table<T> property passing this new entity instance as a parameter. When this is done, the DataContext will begin identity and change tracking on that entity object.

Change Processor:

When you call SubmitChanges() method, the DataContext object’s change processor manages the update to the database. First, the change processor will insert any newly inserted entity objects to its list of tracked entity objects. Next, it will order all changed entity objects based on dependency. Then, if no transaction is in scope, it will create a transaction so that all SQL commands carried out during this invocation of SubmitChanges will have transactional integrity.  It uses SQL Server’s default isolation level of ReadCommited, which means that data read will not be physically corrupted and only committed data will be read, but since the lock is shared, nothing prevents the data from changing before the end of the transaction. Lastly, it will enumerate through the ordered list of changed entity objects, creating necessary SQL and executing them.


Entity classes are responsible for change notification, graph consistency, and implementing good practices.

Change Notification:

The DataContext must be able to monitor this Entity class and know what changed and when it is changed. The Entity class must notify the DataContext that something has changed, in some form or fashion.

Graph Consistency:

Updating the relationship between two entity objects, such as Products and Orders. The reference on each side of the relationship must be properly updated so that each entity object refers to each other (or no longer refers if removed).

Implementing Good Practices:

Entity classes should implement INotifyPropertyChanging and INotifyPropertyChanged. If you decide to make an entity class by hand, and do not implement this and change notification, the DataContext will need to create 2 copies of each entity object: one with original copy, to compare and determine changes (highly inefficient).

Add OnCreated to the constructor of the entity class so that the DataContext knows it is created and create partial methods of [PropertyName]Changing / [PropertyName]Changed for each property and add it before and after each set of that property.


Examples showing how all these responsibilities work

Examples of how it accomplishes change notification, and graph consistency (as taken from the book Pro Linq):

[Column(Storage="_ShipCountry", DbType="NVarChar(15)")]
public string ShipCountry
{
       get
       {
              return this._ShipCountry;
       }
       set
       {
              if ((this._ShipCountry != value))
              {
                     this.OnShipCountryChanging(value);
                     this.SendPropertyChanging();
                     this._ShipCountry = value;
                     this.SendPropertyChanged("ShipCountry");
                     this.OnShipCountryChanged();
              }
       }
}

As you can see in this example, the get part of this property is relatively simple. When we take a look at the set part of this property, we can see it is calling the INotifyPropertyChanging and INotifyPropertyChanged versions of SendPropertyChanging and SendPropertyChanged. This is to let the DataContext know that this property is about to change and has actually changed.

The other two odd looking methods to notice is the OnShipCountryChanging and OnShipCountryChanged methods. This is the partial methods that the user can attach to (if they decide to partial out this entity class) to add validation or additional logic if they so choose. Partial methods are like lightweight Event Handlers, in that you can stub them out in one partial class definition, and actually define them in another partial class definition. But if they are never defined in another partial implementation, the compiler removes all traces that the partial method ever existed. So it is a very efficient way to add functionality, and if you never use it, it isn’t added to the compiled code – hence like a lightweight event.

public Order()
{
       this._Order_Details = new EntitySet<Order_Detail>(
                           new Action<Order_Detail>(this.attach_Order_Details),
                           new Action<Order_Detail>(this.detach_Order_Details));


       this
._Customer = default(EntityRef<Customer>);
       OnCreated();
}

private void attach_Order_Details(Order_Detail entity)
{
       this.SendPropertyChanging();
       entity.Order = this;
}

             

private void detach_Order_Details(Order_Detail entity)
{
       this.SendPropertyChanging();
       entity.Order = null;
}


This part of the example sets up the relationship to the Order Entity object. It sets up the child objects Order_Details, and its parent object Customer. The interesting thing here to note is the fact that the parent object is of type EntityRef<ParentObject> and the child object is of type EntitySet<ChildObject>. EntityRef and EntitySet are generic types that allow the deferred loading to occur. Meaning, they simply state what the relationships are, but do not actually load the references, until it is absolutely necessary. The main difference is EntityRef is a single object that represents the fact that it is a parent and EntitySet is a collection of objects that represents a set of children.

You can see above in this example that EntitySet<Order_Detail> gets instantiated with two Action delegates. This is to specify how to attach and how to detach. It will use these mechanisms to add the children and remove the children to this relationship. Adding will take place when you manually add a new or existing Order_Detail object to this Order object, and remove will occur when you Remove it. This setup is there because to remove or add a relationship, requires it be done on two sides. If you are adding a child object to a parent object (such as adding a Order_Detail object instance to an Order object), you must tell both the Order_Detail object that it is now a child of the Order object (setting its parent), and tell the Order object that it now contains a new child object of that Order_Detail instance. The above example deals with this new child object and how to attach to this parent object (as you can see in the attach_Order_Details method above).

Simply put, LINQ to SQL will use these two action delegates to assign a Order to an Order_Detail, or remove an assignment of Order from Order_Detail. This and the previous example is how Change Notification works and functions in LINQ to SQL, and how the DataContext knows what to update, remove, and insert.

[Association(Name="Order_Order_Detail", Storage="_Order_Details", OtherKey="OrderID")]
public EntitySet<Order_Detail> Order_Details
{
       get
       {
              return this._Order_Details;
       }
       set
       {
              this._Order_Details.Assign(value);
       }
}


In the Order_Detail (children reference) example above, it simply returns out the EntitySet collection of the children objects and maintains the deferred execution until you absolutely need it. When the child objects are needed, it executes the relevant SQL and grabs the child objects. It then calls the set part of this property which re-assigns the EntitySet with the loaded child objects.

[Association(Name="Customer_Order", Storage="_Customer", ThisKey="CustomerID", IsForeignKey=true)]
public
Customer Customer
{
       get
      
{
              return this._Customer.Entity;
       }
       set
      
{
              Customer previousValue = this._Customer.Entity;
              if (((previousValue != value)
                     || (this._Customer.HasLoadedOrAssignedValue == false)))
              {
                     this.SendPropertyChanging();
                     if ((previousValue != null))
                     {
                           this._Customer.Entity = null;
                           previousValue.Orders.Remove(this);
                     }
                     this._Customer.Entity = value;
                     if ((value != null))
                     {
                           value.Orders.Add(this);
                           this._CustomerID = value.CustomerID;
                     }
                     else
                    
{
                           this._CustomerID = default(string);
                     }
                     this.SendPropertyChanged("Customer");
              }
       }
}

 

In the Customer (parent reference) example, we will skip the get part of the Property as it is fairly obvious what it is doing and focus on the set part.

Customer previousValue = this._Customer.Entity;


You can see that the first line of the set method code, they store off a copy of the original Customer assigned. Don’t let the fact that it is calling Entity on the _Customer member confuse you. _Customer is of type EntityRef<Customer>, so in order to get the actual customer, we actually have to call directly to it.

if (((previousValue != value)
       || (this._Customer.HasLoadedOrAssignedValue == false)))

The above statement is checking to see if the Customer is currently being assigned to an existing customer. If it is the same customer that is already assigned, there is nothing more to do.

this.SendPropertyChanging();


As part of the change tracking system, this is notifying the DataContext that we are about to change the Customer Property as part of the Change Tracking / Notification piece.

if ((previousValue != null))
{
       this
._Customer.Entity = null;
       previousValue.Orders.Remove(this);
}


This next part of the code determines if the previous Customer object is null. If it isn’t null, then clear out the relationship between the previous parent and this child object. The inner two lines simple removes the parent object reference and the child reference to this object (in the previous parent). Calling the Remove method above will cause the Customer class’s detach_Orders (similar to the top example) to get called and the passed Order object to be removed. In the detach_Orders method, the passed Order object’s Customer property is set to null and looks like the following:

private void detach_Orders(Order entity)
{
      this.SendPropertyChanging();
      entity.Customer = null;
}


As you can see, when the Customer property is set to null, this will cause the Order object’s Customer property’s set method to be called, which is the method that invoked the code that called the detach_Orders method. So the very method that started this process of removal is getting called recursively.

set
{
       Customer previousValue = this._Customer.Entity;
       if
(((previousValue != value)
              || (this._Customer.HasLoadedOrAssignedValue == false)))

 


Remember how we set the Customer parent object to null before we called the detach_Order method? Well, because of this, the previousValue is set to null, and since we are passing in null, stops the execution here without doing anything else.

So, once the recursion call to the set method returns, we no longer have a reference between the prior parent and that parent to this child object. We are now back to the next line of our code.

this._Customer.Entity = value;
if ((value != null))
{      
       value
.Orders.Add(this);
       this._CustomerID = value.CustomerID;
}
else
{
       this._CustomerID = default(string);
}


The above first line sets the new parent object to the _Customer member to maintain the parent relationship. The next line will check the value to make absolutely sure it is not null. If it was null, it would just assign the default value. If it isn’t null, we will set the new parents child reference to point to this object. The current Order object will be passed to the Customers collection of child Order objects. If it was null, it would just assign the default value.

The result of this will cause the attach_Order method to be called. This will assign the current Order object’s Customer object to the passed Customer, resulting in the Order object’s Customer property’s set part being called again (the second part of the recursion).

       if (((previousValue != value)
              || (this._Customer.HasLoadedOrAssignedValue == false)))

Just like previous, this line will break the recursion. Remember “this._Customer.Entity = value;”, before our recursion out, we set the Oreder object’s Customer property to the new Customer, who was passed this set part again from the attach_Orders method. Since they are the same, this exits out the recursion the same way the detach did.

The last thing of relevance is setting the Customer ID from the new Customer parent, and the letting the DataContext know that this property was changed via the
this.SendPropertyChanged("Customer") part. 

This whole system is required to maintain a one-to-many relationship, between the Entity objects and maintain the graph consistency between them. If you decide to write an Entity class by hand, you must remember to implement a feature similar to this, as the Entity class is responsible for its own graph consistency. A typical approach (if you really want to make your own entity class), is to allow the ORM create these classes for you, and copy the code and paste it into your own Entity class. This will cut down on the amount of work you need to do to maintain change tracking and graph consistency.

It may take a couple of re-reads to fully get what is accomplished here, but it will be worth it to fully understand how all of the change tracking and graph consistency “magic” occurs. If you truly want a deeper understanding of these concepts, I highly recommend reading the book “Pro LINQ” I mentioned earlier. It opened my eyes to a lot of the inner workings of LINQ in general.

Some of the key components not mentioned in this article is the concept of Expression Trees. This is essential to how LINQ to SQL works. In future blog articles I will try to get more in depth with this concept, and how they relate to the .NET Framework 3.5 as a whole. For now I highly recommend reading the article posted here. Another thing I would like to touch on in the future is the inner workings of the DataContext, and how it accomplishes the responsibilities.


kick it on DotNetKicks.com