I am kind of confused about how Lazy loading working.
For example if I have supplier object, which have Address foreign object as a property, like this:
public class Supplier
{
public int ID { get; set; }
[Required]
public string FullName { get; set; }
public string TaxNumber { get; set; }
public virtual Address DeliveryAddress { get; set; }
}
when I put a break point at:
var suppliers = dbContext.Supplier.ToList();
I can see that Address information are available to the var suppliers, etc. when I expend the DeliveryAddress property, it is avaliable, is that means all the FK object has been loaded? But on the other hand, for the query on the right hand I can view that from Visual Studio at the break point, and it is like that:
{SELECT
[Extent1].[ID] AS [ID],
[Extent1].[FullName] AS [FullName],
[Extent1].[TaxNumber] AS [TaxNumber],
[Extent1].[DeliveryAddress_ID] AS [DeliveryAddress_ID]
FROM [dbo].[Suppliers] AS [Extent1]}
Which means the query itself wouldn't tying to load the Address object at all?
So who is loading the FK objects? ToList() or VS debugger?
Other suggestion about how to confirm that whether it is Lazy loading or not?
Note: So now I confirmed that Lazy loading is working by two ToList call, one set Lazy loading off, and another set lazy loading on. Could someone point me to a way to know at what point when lazy loading another query was sent for FK property?
The VS debugger loads the related object and it happens with a second SQL query, not the one you have shown in your question. When you drill into the address object in the debugger, the debugger accesses properties of the object to display their values. Accessing this object triggers lazy loading and the second SQL query.
Edit
This works because the parent object is not your Supplier type but a class which is derived from Supplier (a "proxy"). This derived class is created dynamically at runtime and has some cryptic autogenerated name (you should see this class name in the debugger). This dynamic class has the same properties as your base Supplier but it has overloaded the DeliveryAddress property. (That's the reason why those navigation properties must be virtual, otherwise overloading wouldn't be possible.) The query uses the FK column value which has already been fetched with your supplier query and retrieves the address by this value.
The new getter of the overloaded DeliveryAddress property which is called when you or the debugger accesses the property with supplier.DeliveryAddress contains at runtime generated code which runs a SQL query to load the related object from the database. The derived proxy class holds various additional internal members, especially a reference to the context/database connection (to be able to run a query at all) and a flag which indicates for the proxy object that it already has loaded the navigation property, so that it doesn't run a second redundant query when you access the DeliveryAddress a second time.
That's in short the way how lazy loading with POCOs works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With