Entity Framework 3.5 - Как загрузить детей

Мои вопросы, вероятно, очень просты, как вы загружаете дочерние/подклассы. Нет никакой "нагрузки" или чего-то подобного, что я могу найти, чтобы контекст загружал детей.

класс контекста имеет тип ObjectContext, см. ниже:

public partial class RTIPricingEntities : global::System.Data.Objects.ObjectContext

Продукт

Product.ModifiedByUser(как загрузить этот класс при загрузке продукта?)

Product.Category(как загружать категории при загрузке продукта?)

Ответ 1

Вы можете загружать:

var q = from p in Context.Products
                  .Include("ModifiedByUser")
                  .Include("Category")
        select p;

... или проект:

var q = from p in Context.Products
        select new 
        {
           Id = p.Id,
           Name = p.Name
           ModifiedByUserName = p.ModifiedByUser.Name,
           CategoryName = p.Category.Name
        }

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

Обновление

Да, важно упомянуть, что вы используете службы RIA. Я полагаю, вы также работаете в клиенте. Это делает вещи совершенно разными.

В службах RIA очень важно убедиться, что вы возвращаете весь граф объектов, которые вам требуются при начальной загрузке. Вы не хотите называть что-то вроде .Load() для объекта, потому что это будет еще один горячий сервер, что плохо для производительности. Если вы находитесь, например, в Silverlight-клиенте и запрашиваете список экземпляров с сервера, а их связанные свойства еще не реализованы, то уже слишком поздно. Кроме того, Include не будет работать в клиенте Silverlight. Таким образом, RIA Services имеет серверные инструменты, которые вы можете использовать, чтобы гарантировать, что вы сначала вернете правильный, полностью материализованный графа объектов.

Вместо этого вам нужно использовать IncludeAttribute внутри вашего сервера служб RIA. Вы можете создать класс метаданных "приятель", чтобы украсить вашу модель сущности с помощью [Включить]. Примеры из документа обзора служб RIA, раздел 4.8.

Ответ 2

Использование .Include(), как многие другие предложили, - отличный способ добиться того, что вам нужно.

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

В случае сингулярного отношения типа "Product.Category" (где Product.Category является вашим навигационным свойством от продукта к категории), у вас, скорее всего, также есть элемент "Product.CategoryReference". Вы можете проверить это, если он загружен или нет, а если нет, вы можете загрузить его "по запросу":

if(!Product.CategoryReference.IsLoaded)
{
    Product.CategoryReference.Load();
}

Теперь ваша ссылка на "Категория" должна быть в памяти и готова к использованию.

Если у вас есть свойство навигации, которое ссылается на коллекцию вещей (например, "Части" для продукта), вы можете сделать то же самое непосредственно с помощью свойства навигации:

if(!Product.Parts.IsLoaded)
{
    Product.Parts.Load();
}

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

Марк

Ответ 3

Вы можете использовать метод Include() System.Data.Objects.ObjectQuery. Этот метод указывает связанные объекты для включения в результаты запроса, а вызовы Include() могут быть соединены вместе для загрузки нескольких связанных объектов.

Например, для загрузки ModifiedByUser и Category вы должны использовать такой запрос:

var q = from p in context.Products.Include("ModifiedByUser").Include("Category") 
        select p;

Если ваш объект Category также имеет объект ModifiedByUser, который вы хотите загрузить, вы бы использовали такой запрос:

var q = from p in context.Products
              .Include("ModifiedByUser")
              .Include("Category.ModifiedByUser") 
        select p;

Подробнее см. Формирование результатов запроса в MSDN.

Ответ 4

Я заметил, что вышеупомянутое решение Craig не загружает ModifiedByUser и Category. Он загружает только последний набор объектов, который в данном случае является "Категория".

var q = from p in Context.Products
              .Include("ModifiedByUser")
              .Include("Category")
    select p;

Однако, если вы меняете порядок, чтобы сделать его .Include("Category").Include("ModifiedByUser"), загрузится ModifiedByUser. Самое странное, что свойство IsLoaded как для коллекции объектов будет показывать "true", но Count для первого набора объектов всегда будет равен нулю. Не знаю, почему это так.