Entity Framework - готовая к загрузке связанная сущность - PullRequest
12 голосов
/ 08 сентября 2010

Я использую Entity Framework 4 с MVC и должен убедиться, что все ссылочные объекты, которые я хочу использовать в моем представлении, были загружены до возврата метода контроллера, в противном случае представление выплевывает страшное:

Экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения.

При прямом выборе из контекста я могу просто использовать метод Include(string), чтобы заставить ихбыть включенным в сгенерированный запрос SQL:

var sellers = context.Sellers.Include("Recommendations.User").ToList();

Однако, если у меня есть (например) вспомогательный метод, который принимает сущность и требует загрузки всех элементов, метод Include недоступен.

void Test(Seller seller)
{
    // ensure all recommendations and their users are loaded
}

Подход с использованием грубой силы заключается в их циклическом цикле:

foreach (var recommendation in seller.Recommendations)
    recommendation.User.ToString(); // just force a load

Если у меня будет 100 рекомендаций, это создаст 101 SQL-запрос за кулисами.В идеале я хочу метод / подход, который загружает все Recommendation И User объекты только с одной поездкой в ​​SQL.

Покажите мне деньги.

РЕДАКТИРОВАТЬ Мне не очень интересно обсуждать, хорошая это архитектура или плохая.Я упростил свой сценарий ради вопроса.Можете ли вы сделать то, что я спрашиваю, с EF API?

РЕДАКТИРОВАТЬ 2

Правка Ладислава давала надежду на новый подход, но этокажется, я не совсем там.

Я могу достичь того, что хочу, с помощью этого:

context.Sellers.Include("Recommendations.User").Single(s => s.Id == seller.Id);

Этот подход не работает с использованием LoadProperty ...

context.LoadProperty(seller, "Recommendations.User");

... поскольку происходит сбой с ошибкой ...

Указанное свойство навигации Recommended.User не найдено.

Ни один из этих подходовработать, если у вас нет ссылки на контекст.

Ответы [ 4 ]

5 голосов
/ 26 февраля 2014

Это старый вопрос, но в EF6 вы можете выполнить загрузку зависимых объектов на объект, например this :

context.Entry(seller).Collection(s => s.Recommendations).Query().Include(r => r.User)).Load();

Это загрузит все Recommendations и связанные с ними Users для данного seller

3 голосов
/ 08 сентября 2010

Я думаю, что это работа для вашего репозитория, которая в вашем случае должна предоставлять такие методы, как GetFullSeller (все свойства загружаются с помощью Include) и GetSeller (только базовая сущность).

Существует несколько способов загрузки свойств навигации в EF v4.

  • Стремительная загрузка (с использованием Include)
  • Ленивая загрузка
  • Явная загрузка ObjectContext.LoadProperty (не работает для POCO)

Автоматическая загрузка отсутствует.

2 голосов
/ 03 ноября 2010

Я в такой же ситуации. Я думаю, что с EF очень легко попасть в проблему с 101 запросом.

Решением может быть создание частичного класса вашего класса Продавца (сгенерированного EF) и реализация GetSubclassNameQ, которая возвращает IQueryable, и GetSubclassNameQFull, которые возвращают IQueryable с энергичной загрузкой.

public partial class Seller{

  public IQueryable<Recommendation> GetRecommendationsQ(EntityContainer entitycontainer) {
    return entitycontainer.Recommendations;
  }      

  public IQueryable<Recommendation> GetRecommendationsQFull(EntityContainer entitycontainer) {
    return this.GetRecommendationsQ(entitycontainer).Include("Recommendations.User");
  }

  public IQueryable<Recommendation> GetRecommendationsQ() {
    return GetRecommendationsQ(new EntityContainer());
  }

  public IQueryable<Recommendation> GetRecommendationsQFull() {
    return this.GetRecommendationsQ().Include("Recommendations.User");
  }

}
0 голосов
/ 08 сентября 2010

Вместо того, чтобы передавать ваши фактические доменные объекты (EntityObject s) в представление, вы можете использовать свой контроллер для отображения их в объект Model, который лучше отображает то, что фактически должно отображать ваше представление. Это уменьшит количество логики, требуемой в вашем представлении, и будет иметь приятный побочный эффект - избегать передачи объектов EntityObject после истечения срока их контекста.

Редактировать на основе ваших правок:

Нет, у API нет способа взять один объект Entity Object и сделать каждый объект Entity Object его типа, который был загружен в то же самое время, что он был заполнен определенным свойством одним махом. Вам лучше всего сначала вытащить все предметы, используя упоминание Include, как показано в вашем вопросе.

...