views:

218

answers:

6

I find myself repeating bits of code like this over and over while using ADO.NET Entity Framework.

VB:

' Load the thing if not already loaded. '
If Not Something.Thing.IsLoaded Then
    Something.Thing.Load()
End If

C#:

// Load the thing if not already loaded.
if (!Something.Thing.IsLoaded)
{
    Something.Thing.Load();
}

Is this normal? Should I be using IsLoaded and Load so often? Or am I not using this correctly?

+1  A: 

If you are for example loading a list of 7 customers and then loading the orders for each of the customers.

If you do it by loading the customers, then looping through each customer, checking if the orders are loaded and then loading them. you will get 8 (1+7) calls to the database.

If you instead used Include("Orders") when getting the customers, there would be no loop, no if statement, and only a single call to the database.

Entity Framework 4 will have lazy loading.

Shiraz Bhaiji
Using Include does not guarantee you won't still get 8 calls to the database.
Michael Maddox
+3  A: 

Depending on how you call the object (ex. repository), what you can do is use the "Include()" method on the entity base set.

     return EntitiesObject.Something.Include("Thing").Where(x=>x.ID == ID)

Doing so would return the object(s) with "Thing" already loaded.

Here is a good article about it:

http://msdn.microsoft.com/en-us/library/bb896272.aspx

Baddie
Include does not force anything to be loaded. You still must call IsLoaded and Load after using Include if you want to make sure it gets loaded. Include should "eager" load things, but it is a hint only.
Michael Maddox
+1  A: 

I echo what Shiraz has said. Also, I often find myself implementing lazy-loading by wrapping the EF-generated property within a partial class. Here's an example:

public partial class Customer
{
      public EntityCollection<Order> CustomerOrders
      {
          get
          {
              if (!Orders.IsLoaded)
                  Orders.Load();

              return Orders;
          }
      }
}

Saves some repetition on the calling side.

HTH, Tim

Tim Ridgely
+3  A: 

The version of the EntityFramework in the VS2010 beta is much, much friendlier in this regard. That said, if you're stuck with the version without lazy-loading, this extension method may help you:

public static T EnsureLoaded<T>(this EntityReference<T> eRef) where T: class, IEntityWithRelationships
{
    if (!eRef.IsLoaded)
        eRef.Load();

    return eRef.Value;
}

Then, assuming you have User objects that have Contacts, you could do:

Contact c = User.ContactReference.EnsureLoaded();

It's still pretty sucky, but I find it preferable to writing that IsLoaded if statement over and over.

tclem
See also Proviste's answer.
Zack Peterson
+1  A: 

That is totally normal and expected. It makes performance optimization difficult though. Unfortunately, the Include statement still requires IsLoaded and Load to be called afterward if you want to ensure your objects got loaded.

Michael Maddox
+1  A: 

hi

i have extended tclem solution for 1-n relationships :

public static EntityCollection<T> EnsureLoaded<T>(this EntityCollection<T> eRef) where T : class, IEntityWithRelationships
{
    if (!eRef.IsLoaded)
        eRef.Load();

    return eRef;
}
Proviste