Knocking off Danny Simmons Entity Framework Beta 2 List: #2: Span

[#1: Complex Types]

The next item in Danny’s list that I wanted to look at was this:

·         Better support for span over LINQ to Entities queries

The span feature makes it possible to pre-fetch related entities.  In previous CTPs span was specified through a property on ObjectQuery<T>, but in this CTP span has been changed to work as a builder method, Include, which makes it simpler to specify span rules in LINQ to Entities queries.  Include can be called on the ObjectQuery used in the from clause of the LINQ query.

This is low-hanging fruit for me because I had seen the use of SPAN in March and tried it out when it was released with the June CTP. Here is the blog post I wrote at that time.

The use of span changed a lot since then. In fact, the word “span” no longer exists!

Previously you had to tell the object context that you wanted to include child data before you actually ran the query. Now you include that instruction in the query itself by attaching the Include property to the object in the query like this query which says to grab the SalesorderHeader info along with the customers.

 Dim custQuery = From cust In aw.Customer.Include(“SalesOrderHeader”)_
 Where cust.SalesPerson = “adventure-works\jae0” Select cust
  For Each c In custQuery
   Debug.Print(c.CompanyName & “…………..”)
   For Each so In c.SalesOrderHeader
    Debug.Print(so.OrderDate)
   Next
  Next

You could also drill in further

   Dim custQuery = From cust In aw.Customer.Include(“SalesOrderHeader.SalesOrderDetail”) _
   Where cust.SalesPerson = “adventure-works\jae0” Select cust
   For Each c In custQuery
    Debug.Print(c.CompanyName & “…………..”)
     For Each so In c.SalesOrderHeader
       Debug.Print(so.OrderDate)
           For  Each sd In so.SalesOrderDetail
              Debug.Print(“…” & sd.OrderQty)
          Next
       Next
    Next

This would get the headers and their child detail records.

You can also define multiple collection properties to grab such as here where I get the salesOrderHeaders and the Addresses for the customer. Looking at how to get at the addresses makes me really happy to have entity framework and the associations doing this job. What a pain in the rear the joins would be otherwise!

  Dim custQuery = From cust In aw.Customer.Include(“SalesOrderHeader”).Include(“CustomerAddress.Address”) _
   Where cust.SalesPerson = “adventure-works\jae0” Select cust
  For Each c In custQuery
   ‘c.SalesOrderHeader.Load()
   Debug.Print(c.CompanyName & “…………..”)
   For Each so In c.SalesOrderHeader
    Debug.Print(so.OrderDate)
   Next
   For Each add In c.CustomerAddress
    Debug.Print(“Cust City: ” & add.Address.City)
   Next
  Next

Outputs:

Action Bicycle Specialists…………..
6/1/2004
Cust City: Woolston
Central Bicycle Specialists…………..
6/1/2004
Cust City: Maidenhead
Downhill Bicycle Specialists…………..
Cust City: Berks
Metropolitan Bicycle Supply…………..
6/1/2004
Cust City: London

I looked to see if you could skip a generation eg aw.Customer.Include(“SalesOrderDetail”), but that didn’t pan out. Makes sense, but it only took an extra 5 seconds to be sure.

The nice thing is that include is now explicitly tied to the objectQuery it is used in. No more resetting the object context.

So if you want to do another similar query, you won’t get the related data unless you ask for it. Getting what you ask for is part of the mantra of Entity Framework. No assumptions are made.

Dim custQuery = From cust In aw.Customer.Include(“SalesOrderHeader”) _
   Where cust.SalesPerson = “adventure-works\jae0” Select cust

 Dim custQuery2 = From cust In aw.Customer _
    Where cust.SalesPerson = “adventure-works\shu0” Select cust

The 2nd query will only bring back customer data. If you want SalesOrderHeaders, you will need to explicitly load them as you iterate through the customers.

For Each c In custQuery2
   c.SalesOrderHeader.Load()
   Debug.Print(c.CompanyName & “…………..”)
   For Each so In c.SalesOrderHeader
    Debug.Print(so.OrderDate)
   Next
  Next

  Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!  

4 thoughts on “Knocking off Danny Simmons Entity Framework Beta 2 List: #2: Span

  1. Julie,I’m disappointed to see late-binding introduced into LINQ to Entities. This negates one of LINQ’s primary features.–rjhttp://oakleafblog.blogspot.com/2007/08/linq-and-entity-framework-updates-for_30.html

  2. RogerI agree. After I typed CustOrderDetail wrong 3 times (and didn’t find out until run time), I asked the powers that be about the use of the string in the LINQ query and if they can’t just leverage the schema that LINQ is already aware of.I’m hoping that the use of the string is just their first pass? (Ever the pollyanna)(I made a similar comment on your blog post)

  3. Julie I agree. They could have used an Expression to refer to these fields, for eg: include(c => c.CustomerAddress); which preserves verifiability at compile time.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.