Daily Archives: October 2, 2007

Resources for LINQ talk at San Diego .NET

Last week I did something that may have seemed  a little silly to some, but was a great deal of fun. I left my house at 7am, drove to the airport, flew all the way across the country (from the northeast corner of the U.S. to the southwest corner) to San Diego to give a 2 hour presentaiton to the San Diego Dot Net user group on behalf of INETA.

The silly part was that I spent about 15 hours on 4 different planes to give a 2 hour talk. But I loved doing it!

Frankly, 15 hours on planes gives me more productive work time than I have when I’m working in my home office. Probably a good 10 extra hours! No phone, no email, no distractions. I’m stuck on a plane with my laptop and hopefully a movie that I have no interest in seeing and I can just work work work! Well, the movie on the way out was good and it even made me cry (darn I hate that). On the way back it was Fantastic Four – no interest whatsoever.

The other great part about this trip was that I got to spend some great quality time with a friend as well as  an hour by the ocean on Wednesday morning before heading to the airport to return home.

And of course, I got to do one of my most favorite things – present at a user group  on a topic that I find fascinating. My talk was about LINQ. Originally I had hoped to “practice” a talk on ASP.NET Databinding with LINQ that I’ll be doing in November at DevConnections.  I had added some introductory LINQ information to the beginning of the talk as Brian Loesgen, the group leader, told me in advance that they haven’t had a LINQ talk yet.

At the start of the meeting, I asked for a show of hands on who had used LINQ already – only two people. So I ended up focusing on the intro part and just showing some of the databinding quickly at the end. The intro stuff includes the always fascinating language enhancements that enable LINQ and then a quick tour of all of the LINQ “flavors” – objects, datasets, xml, entities and of course, LINQ to SQL. That is a lot of fun to go over.

I made the executive decision to try to write some C# code on the fly, which never goes well – especially at bed time. If you consider the time zone difference I started the talk at 10pm. But I aim to entertain, and I certainly didn’t disappoint much to a bit of embarrassment on my part. Semi-colons are not an issue. I remembered square brackets rather than parens. But this time it was the spacing that got me. VB just takes care of so many little syntax problems you might forget. C# is 100% unforgiving.

Getting past that, I had a blast and managed somehow to wrap up just about on time even though I could have gone on and on for hours more.

Throughout the course of the talk, I mentioned some great articles and resources and wanted to put them all in one place so here they are:

101 LINQ Queries for C#

101 LINQ Queries for VB

Great LINQ overview article by Don Box and Anders Hejlsberg

Lambda Epxressoins article for VB coders

VB Deep Dive articles by Bill McCarthy in Visual studio Magazine – There seems to be no list of all the columns, you have to go look in each issue in the archives. Here is Bill’s blog.

The LINQ Project: consolidated starting point for MSDN materials

LINQ best practices for VB (webcast)

Books I mentioned:

Already published Introducing Microsoft LINQ from MS Press

Coming soon LINQ in Action

Blogs I mentioned:

Roger Jennings

Jim Wooley

LINQ in Action blog

Mike Taulty

Scott Guthrie’s LINQ to SQL post series

XML Serializing Entity Framework entities with their children for SOA

Another challenge in working with tiered solutions (notably web services) that require xml serialization of entity objects is that the xml serializer does not serialize the entire graph. It only gets the main object and drops all of the relations. This is not because Entity Framework is trying to be mean, just related to how XML serialization works. In fact, the binary serialization gets the entire graph. But in the web services scenarios, we need XML.

So how to go about passing the full graph from client to server and back or server to server? I had a few ideas of how to approach this but was given a suggestion by Danny Simmons that would help me create something that would be more aligned with what their thinking on this is.

This solution uses a facade pattern. It is possible because the individual objects are serializable and a generic List is serializable. Conceptually, I take all of the objects in the graph that may start out, for example as:

-Customer
  – Orders

and create Lists of each set of objects then combine those lists into another object. After this is created, the above would look like this

-List(Of Customer)   –> would only contain one
-List(Of Orders)

Deserializing would mean pulling the customer out of the first list, then iterating through the list of orders and adding each order to that customer.

It gets a little more complicated when dealing with deeper graphs.

-Customer
  – Order
     – OrderDetails
  – Order
     -orderDetails

now we need to serialize a bit more carefully

-List(Of Customer)
-List(Of OrderwithDetails)

The OrderswithDetails would be another object that looks like this

-List(Of Order)
-List(Of OrderDetails)

The OrderwithDetails class that implements the facade will need these features:

  1. A property to contain List(Of Order)
  2. A property to contain List(Of OrderDetails)
    1. if we are going deeper then this property should be List(Of OrderDetailswithChildren)
  3. Instantiation code needs to take in the original object and construct the lists
  4. A method that knows how to deserialize the object and return the real object, not the lists of it’s parts
  5. If this is going to be used in a wcf service, the class needs to be marked as a DataContract and the properties should be marked as DataMembers.

Here is what a simple class for serializing/deserializing the orders with their orderDetails (without considering any possible children of orderDetails right now). This is my first pass at this class and therefore it is not generic code that will work with any complex object. However, it does work out the basic logic (and it does work!).

<Serializable()> _
<DataContract()> _
Public Class SalesOrderwithDetailsGraph
Dim _order As List(Of SalesOrderHeader)
Dim _orderdetails As List(Of SalesOrderDetail)

Public Sub New()
‘required for serialization
End Sub

Public Sub New(ByVal salesOrderGraph As SalesOrderHeader)
 _order = New List(Of SalesOrderHeader)
 _order.Add(salesOrderGraph)
 If salesOrderGraph.EntityState <> EntityState.Detached Then
    ‘if I’m just creating the order for the first time and am attached to the context,
    ‘this assumes that I didn’t Include salesorderHeaders in my query – big assumption, but
    ‘it is just for my proof of concept. If it’s detached, then I am already working with a 
    ‘full object and can’t load anyway – that requires a context and a connection
   
salesOrderGraph.SalesOrderDetail.Load()
 End If
 _orderdetails = New List(Of SalesOrderDetail)(salesOrderGraph.SalesOrderDetail)
End Sub

<DataMember()> _
Public Property Order() As List(Of SalesOrderHeader)
 Get
  Return _order
 End Get
 Set(ByVal value As List(Of SalesOrderHeader))
  _order = value
 End Set
End Property

<DataMember()> _
Public Property OrderDetails() As List(Of SalesOrderDetail)
 Get
  Return _orderdetails
 End Get
 Set(ByVal value As List(Of SalesOrderDetail))
  _orderdetails = value
 End Set
End Property

Public Function GetOrderFromGraph() As SalesOrderHeader
 ‘this is to Deserialize
  Dim ord As SalesOrderHeader
 ‘there will only be one header in the object
 ord = _order(0)
 For Each sod As SalesOrderDetail In _orderdetails
  ord.SalesOrderDetail.Add(sod)
 Next
 Return ord
End Function

End Class

Now, if i have a simple scenario where I have a client that requests an order from a web service, mucks with that order, then sends it back to the service for an update, the client can start by retrieving a SalesOrderGraph, deserializing it back to a SalesOrder, then when it’s done, create a SalesOrderGraph from the existing SalesOrder and pass it back up to the Service.

There’s one big missing piece here and I blogged about that yesterday. When the order gets back to the service for an update, if you plan to update through the objectContext, then you will need to manually set the state to modified. You can do this with or without original data (depending on whether or not you care about concurrency). See my blog post about Disconnected Entities.

Lastly, I have actually gone the next step with the above serializer so that i can get a Customer with Orders and OrderDetails. It means bulding a CustomerGraph just as I built the Order Graph, but the children of the Customer will be SalesOrderwithDetailGraph objects, rather than just SalesOrderHeaders. Then you get a recursive thing happening where the customer knows how to work with it’s orders, and each order know how to work with it’s details.

But this post is long enough already, eh?