Подтвердить что ты не робот

Entity Framework - надежные объекты, связанные с загрузкой

Я использую 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 AND User только с одной поездкой в ​​SQL.

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

EDIT Мне не очень интересно обсуждать, является ли это хорошей или плохой архитектурой. Я упростил свой сценарий ради вопроса. Можете ли вы сделать то, что я прошу с помощью API EF?

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

Ladislav edit предложил надежду на новый подход, но, похоже, я не совсем там.

Я могу добиться того, чего хочу через это:

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

Этот подход не работает, используя LoadProperty...

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

... поскольку он не работает с ошибкой...

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Edit:

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

  • Ожидающая загрузка (с помощью Include)
  • Lazy loading
  • Явная загрузка ObjectContext.LoadProperty (не работает для POCO)

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

Ответ 3

Я в той же ситуации. Я думаю, что с 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");
  }

}

Ответ 4

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

Изменить на основе вашего редактирования:

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