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 не найдено.
Ни один из этих подходов не работает, если у вас нет ссылки на контекст.
Ответы
Ответ 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.
Автоматическая загрузка отсутствует.
Ответ 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
, как вы показываете в своем вопросе.