Lazy Load Entity Framework EntityCollection with criteria

In the Entity Framework (in particular, EF 3.5, but if it exists in EF 4, this gives me a reason to update), is it possible to lazy the load on only part of the collection? Perhaps I am also approaching this wrong, so I am open to suggestions. My tables / entities look something like this:

Person PersonMeal Meal ------ 1---* ---------- *---1 ----- ID ID ID ... PersonID ... MealID Value ... 

I have a list of Person objects that were obtained through the Entity Framework through a stored procedure. I have a view that shows only one Meal at a time, so I only need the information related to this meal. I currently have code that looks like this:

 Function GetPersons() As List(Of Person) Dim personList = context.StoredProcedureCall(param1, param2, param3).ToList() personList.ForEach(Function(x) LazyLoadProperties(x)) Return personList End Function ' Work around function because VB lambdas don't take Sub's Function LazyLoadProperties(ByVal person As Person) As Object If (Not person.PersonMeal.IsLoaded) Then person.PersonMeal.Load() End If Return Nothing End Function 

The problem is loading the entire collection. Provided this is a small collection, so in the worst case, I can download it all and then delete everything except what I need, but it is far from ideal. Plus, I'm not sure that this would be possible without causing any collection change events, since they should not have been there in the first place.

+6
entity-framework lazy-loading
source share
3 answers

In this case, instead of using the Load method, you can simply query the database for your data:

 Function GetPersons() As List(Of Person) Dim personList = context.StoredProcedureCall(param1, param2, param3).ToList() Dim person As Person For Each person in personList person.PersonMeals = From pm in context.PersonMeals.Include("Meal") Where pm.Person.Id == person.Id And pm.Meal.Id == Meal_ID Take 1 Next person Return personList End Function 

I assume that person.PersonMeals is a collection, otherwise you can use FirstOrDefault instead of Take .

In this query, we basically select all PersonMeals objects (together with Meal ) that have the person identifier as the current person in the loop and the desired food identifier. If your database does not have corrupted data (several rows with the same PersonID-MealID combinations), you will get 0 or 1 result, which will be written to your PersonMeals property.

+2
source share

Your question was pretty clear: is it possible to lazily load only part of the collection, but the answer is no! Not in EF1, nor in EF4. By the way, if the last meal is an item, start asking for it! Instead of taking the person and eating food, take the last dishes and the person attached to it.

+1
source share

Yakimych's answer should work, but there were several errors in the code.

The correct syntax should be:

 Private Function GetPersons() As List(Of Person) Dim personList As List(Of Person) = Context.StoredProcedureCall(param1, param2, param3).ToList() For Each p In personList Dim pId As Integer = p.Id p.PersonMeals = (From pm As PersonMeal In context.PersonMeals.Include("Meal") Where (pm.Person.Id = pId And pm.Meal.Id = Meal_ID) Take 1).ToList Next Return personList End Function 

Hope this helps.

0
source share

All Articles