EF: Как сделать эффективную ленивую загрузку (не 1 + N выбор)? - PullRequest
2 голосов
/ 22 октября 2010

Начиная со Списка сущностей и нуждаясь во всех зависимых сущностях через ассоциацию, есть ли способ использовать соответствующие свойства навигации для загрузки всех дочерних сущностей с одним db-round-trip?То есть.сгенерировать одиночный оператор WHERE fkId IN (...) с помощью свойства навигации?

Подробнее
Я нашел следующие способы загрузки дочерних элементов:

  1. Сохранить родительский набор-entities as IQueriable

    • Не хорошо, так как БД должен будет каждый раз находить основной набор и присоединяться, чтобы получить запрошенные данные.
  2. Поместите родительские объекты в массив или список, затем получите связанные данные через свойства навигации.
    var children = parentArray.Select(p => p.Children).Distinct()

    • Это медленно, так как генерирует выбор для каждого основногоentity.
    • Создает повторяющиеся объекты, поскольку каждый набор дочерних элементов создается независимо.
  3. Поместите внешние ключи от основных объектов в массив, а затем отфильтруйте всеЗависимый-ObjectSet
    var foreignKeyIds = parentArray.Select(p => p.Id).ToArray();<br> var children = Children.Where(d => foreignKeyIds.Contains(d.Id))
    Затем Linq генерирует желаемое предложение "WHERE foreignKeyId IN (...)".

    • Это быстро, но возможно только для 1: * - отношений, так как таблицы связей отображаются.
    • Удаляет преимущество читаемости EF благодаря использованию идентификаторов после всех
    • Свойства навигации типа EntityCollection не заполняются
  4. Стремительная загрузка, хотя .Include () - методы, включенные для полноты (запрашивая отложенную загрузку)

    • Предположительно объединяет все включенное вместе и возвращает один гигантский плоский результат.
    • Имеютзаранее решить, какие данные использовать

Есть ли способ получить простоту 2 с производительностью 3?

Ответы [ 2 ]

0 голосов
/ 15 ноября 2011

Я думаю, что найти хороший ответ невозможно или, по крайней мере, не стоит проблем. Вместо этого микро ORM, такой как Dapper , дает большую выгоду, устраняя необходимость отображать столбцы sql и свойства объекта, и делает это без необходимости сначала создавать модель. Также можно просто написать желаемый sql вместо понимания того, что linq написать, чтобы он был сгенерирован. IQueryable<T> будет пропущено, хотя.

0 голосов
/ 04 мая 2011

Вы можете присоединить родительский объект к своему контексту и получить дочерние элементы, когда это необходимо.

foreach (T parent in parents) {
    _context.Attach(parent); 
} 
var children = parents.Select(p => p.Children);

Редактировать: для присоединения нескольких, просто итерируйте.

...