Help me understand the essence of framework 4 caching for lazy loading
I am getting some unexpected behavior with entity framework 4.0 and I hope someone can help me figure it out. I am using Northwind database for the purposes of this question. I also use the default code generator (not poco or self-tracking). I expect that at any time I am requesting a context for the framework just to make the round trip, if I have not yet received those objects. I get this behavior if I disable lazy loading. Currently in my application, I enable lazy loading for a short time and then disable it so that I can achieve the desired behavior. This pretty much sucks, so please help. Here is a good sample code that can demonstrate my problem.
Public Sub ManyRoundTrips()
context.ContextOptions.LazyLoadingEnabled = True
Dim employees As List(Of Employee) = context.Employees.Execute(System.Data.Objects.MergeOption.AppendOnly).ToList()
'makes unnessesary round trip to the database, I just loaded the employees'
MessageBox.Show(context.Employees.Where(Function(x) x.EmployeeID < 10).ToList().Count)
context.Orders.Execute(System.Data.Objects.MergeOption.AppendOnly)
For Each emp As Employee In employees
'makes unnessesary trip to database every time despite orders being pre loaded.'
Dim i As Integer = emp.Orders.Count
Next
End Sub
Public Sub OneRoundTrip()
context.ContextOptions.LazyLoadingEnabled = True
Dim employees As List(Of Employee) = context.Employees.Include("Orders").Execute(System.Data.Objects.MergeOption.AppendOnly).ToList()
MessageBox.Show(employees.Where(Function(x) x.EmployeeID < 10).ToList().Count)
For Each emp As Employee In employees
Dim i As Integer = emp.Orders.Count
Next
End Sub
Why does the first block of code make unpredictable round trips? In the meantime, there is no need to know about it. ”
a source to share
Your expectation is wrong. Queries always query the DB. Is always. This is because LINQ is always converted to SQL.
To load an object from the context if it has already been fetched, and from the DB if it hasn't, use ObjectContext.GetObjectByKey () .
a source to share
The first "unnecessary" trip is necessary - you made a new request and the database might have changed in the meantime. If you used the variable employee instead (where you stored the query result), there would be no need to make a trip to the database.
The second is necessary because you are asking him to receive Orders for each Employee. With Lazy loading and without Include (), it doesn't read Orders until you ask for it with emp.Orders.Count ().
Remember that until you start repeating the query (or call some method that requires iterating over it), LINQ to EF does nothing. If you store this query in a variable and then call .Count () there is a round trip there. If you use the same query and start listing it, there will be another round. If the objects in this query have relationships themselves, and lazy loading occurs each time it is accessed, there will be another round trip.
The following example shows how to do this correctly if you know in advance that you want the orders you want to load. Notice how you don't go back to the context to ask it again about employees, you are reusing the one already loaded.
a source to share