views:

24

answers:

1

I commented out the line of code that enables lazy loading from all the ctor overloads for my ObjectContext class, yet when I iterate over a navigational property, the iteration is successful. Why?

Here's the relevant bits of code.

    public MyExpensesEntities() : 
                 base("name=MyExpensesEntities", "MyExpensesEntities")
    {
        // this.ContextOptions.LazyLoadingEnabled = true;
        OnContextCreated();
    }

    static void Main(string[] args)
    {
    AddExpenses();

       Console.WriteLine("Lazy loading is {0}.", 
                         _context.ContextOptions.LazyLoadingEnabled ? 
                         "enabled": "disabled");

       PrintCategorywiseExpenses();

   _context.Dispose();
       Console.WriteLine("Press any key to exit...");
   Console.ReadKey();
    }

 static void PrintCategorywiseExpenses()
    {
        foreach (var cateogry in _context.Categories)
        {
            Console.WriteLine
                            ("Category: {0}\n----------------", 
                             cateogry.CategoryName);

            foreach (var e in cateogry.Expenses)
                Console.WriteLine
                                    ("\tExpense: {0}\tAmount: {1}", 
                                     e.Particulars, e.Amount.ToString("C"));
        }

        Console.WriteLine();
    }
+1  A: 

You should be aware that by doing a foreach over a navigation property you are explicitly ask EF to load it for you and just because you turn off the Lazy Loading does not mean that you cannot explicitly load them later. So, once it is disabled, you can still explicitly load related data on demand if needed and that's exactly what happened when you use foreach. Another term for "Lazy Loading" is actually "implicit deferred loading" and it will not prevent us from doing an "Explicit deferred loading"

Basically, this line of code:

foreach (var cateogry in _context.Categories)
is almost equivalent to this:

_context.Categories.AsEnumerable()

To see how disable lazy loading affect your code see the example below.
In this example, I disable it and read one of your Categories then dispose the ObjectContext and do the foreach over Expenses:

Category category;
using (MyEntities context = new MyEntities()) {
    category = _context.Categories.First();
}

foreach (var e in cateogry.Expenses)
      Console.WriteLine("Expense:{0}", e.Amount.ToString("C"));
}


LazyLoading is Disabled:
Nothing happens, the code will never get into the foreach since the cateogry.Expenses.Count == 0

LazyLoading is Enabled:
EF tries to lazy load Expenses and since the ObjectContext has been disposed (by going out of using scope) you'll get an System.ObjectDisposedException containing this message:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Morteza Manavi
Then when is the navigational property not loaded? And then how does setting the lazy loading to false affect lazy loading of the navigational property? Could you please give me an example where lazy loading is turned off and the navigational property cannot be accessed?
Water Cooler v2
Sure, I've just added a code snippet to my answer to illustrate it, please check it out.
Morteza Manavi
Many thanks for your answer. I am still reading it again and thinking more deeply about it. I'll have some more questions in the comments soon.
Water Cooler v2
You're very welcome! We'll be in touch then.
Morteza Manavi
Nice answer altough you posted an impossible line of code: var category; you can't use the "var" keyword without assigning a value to the variable in C#, because there is no spoon... wait.. what? I mean, there are no untyped variables in C# ^^
Matteo Mosca
Yep, that's just because I didn't know the name of his entity object for *Categories* ObjectSet. Let's assume it's *Category*. I've changed the code. And you're right, with anonymous types you will initialize the variable on the line of declaration or the compiler will complain. Thanks for the heads-up :)
Morteza Manavi