Ленивая загрузка Entity Framework EntityCollection с критериями - PullRequest
6 голосов
/ 27 мая 2010

В Entity Framework (в частности, EF 3.5, но если он существует в EF 4, это дает мне причину для обновления), можно ли лениво загрузить только часть коллекции? Возможно, я тоже подхожу к этому неправильно, поэтому я открыт для предложений. Мои таблицы / сущности выглядят примерно так:

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

У меня есть список Person объектов, которые были получены через Entity Framework с помощью хранимой процедуры. У меня есть представление, которое показывает только один Meal за раз, поэтому я хочу только информацию, относящуюся к этой еде. В настоящее время у меня есть код, который выглядит так:

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

Проблема в том, что загружается вся коллекция. Конечно, это небольшая коллекция, поэтому в худшем случае я могу загрузить все, а затем удалить все, кроме той, которая мне нужна, но это далеко от идеала. Кроме того, я не уверен, что это было бы возможно без запуска каких-либо событий изменения коллекции, так как они не должны были быть там в первую очередь.

Ответы [ 3 ]

2 голосов
/ 16 октября 2010

В этом случае вместо использования метода Load вы можете просто запросить данные в базе данных:

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

Я предполагаю, что person.PersonMeals - это коллекция, в противном случае вы можете использовать FirstOrDefault вместо Take.

В этом запросе мы в основном выбираем все объекты PersonMeals (вместе с Meal), у которых в качестве текущего человека в цикле указан идентификатор человека и желаемый идентификатор еды. Если в вашей БД нет поврежденных данных (несколько строк с одинаковыми комбинациями PersonID-MealID), будет 0 или 1 результат, который будет записан в ваше свойство PersonMeals.

1 голос
/ 21 октября 2010

Ваш вопрос был довольно ясен: возможно ли лениво загрузить только часть коллекции, и ответ - нет! Ни в EF1, ни в EF4. Кстати, если последний прием пищи является предметом, начните запрашивать это! Вместо того, чтобы извлекать человека и принимать пищу, извлекайте последние блюда и человека, к которому они прикреплены.

0 голосов
/ 18 октября 2010

Ответ Якимича должен сработать, но в коде было несколько ошибок.

Правильный синтаксис должен быть:

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...