Проблемы с загрузкой связанных сущностей (Eager Load) с помощью ObjectContext.CreateQuery (Entity Framework и репозитории)

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

   public ObjectQuery<E> DoQuery(ISpecification<E> where)
   {
        return (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + typeof(E).Name + "]").Where(where.EvalPredicate);
   }

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

Я прочитал, что вы можете сделать .Include("User"), чтобы выполнить Eager Load объекта... но это не работает, когда я пытаюсь это сделать:

public ObjectQuery<E> DoQuery(ISpecification<E> where)
{
     return (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + typeof(E).Name + "]").Include("User").Where(where.EvalPredicate);
}

Я также проверил, чтобы убедиться, что имя набора сущностей и имя модели «Пользователь», что они и есть. Единственное, что я мог придумать, это поместить несколько вещей в ("[" + typeof(E).Name + "]"), но я не уверен, как включить туда несколько объектов... Вот что я пробовал, так как я видел, как кто-то сказал, что вы можете загрузить несколько, поместив файл . между.

public ObjectQuery<E> DoQuery(ISpecification<E> where)
{
     return (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + typeof(E).Name + "].[User]").Where(where.EvalPredicate);
}

Но это не сработало...

Если я не на правильном пути, пожалуйста, дайте мне знать. Кто-нибудь знает, как загружать связанные объекты при использовании ObjectContext.CreateQuery? Любые предложения или идеи помогают.

Спасибо,
Мэтт


person Matt    schedule 31.10.2009    source источник


Ответы (2)


CreateQuery принимает оператор ESQL. Таким образом, вы можете написать что-то вроде:

public ObjectQuery<E> DoQuery(ISpecification<E> where)
{
    var esql = String.Concat(
         "SELECT VALUE e1 FROM OFTYPE(", 
         GetEntitySetName(typeof(E)),
         ", ", 
         typeof(T).FullName, 
         ") AS e1");
    return Context.CreateQuery<T>(esql).Include("User").Where(where.EvalPredicate);
}

... где GetEntitySetName — это написанный вами метод, который возвращает имя набора строковых сущностей для вашего типа сущности или использует стратегия быстрой загрузки.

Почему ОФТАЙП? Если в вашей модели есть наследование, этот ESQL вернет ObjectQuery<TParent> вместо ObjectQuery<TChild> без него.

Наконец, Include работает только в том случае, если сущность E имеет свойство с именем User. Тип и имя набора сущностей не имеют отношения к Include.

person Craig Stuntz    schedule 02.11.2009

Предыдущая версия этого ответа неверна, как указал Крейг в комментариях. Поскольку я не могу удалить этот ответ (из-за комментариев?), я по крайней мере попытаюсь оставить что-то правильное.

Предположим, у вас есть модель (.edmx) с двумя сущностями Product и ProductDetail. Далее предположим, что вы хотите получить данный продукт и связанные с ним сведения.

Я бы убедился, что работает следующее (если у вас есть продукт с идентификатором 1, у которого есть подробные записи):

var result = ctx.CreateQuery<Product>("Products").Include("ProductDetails").Where(p => p.ProductId == 1);

В операторе Include выше ProductDetails — это свойство Product. Если это сработает, я бы попробовал следующее:

public ObjectQuery DoQuery<E>(Expression<Func<E, bool>> filter)
{
    string entitySetName = GetEntitySetName(typeof(T)); 
    return (ObjectQuery<E>)_ctx.CreateQuery<E>(entitySetName).Include("ProductDetails").Where(filter);
}

Обратите внимание, что GetEntitySetName() не является встроенной функцией.

var result = DoQuery<Product>(p => p.ProductId == 1);
person Kim Major    schedule 31.10.2009
comment
Я до сих пор не возвращаю пользовательские объекты... Я поставил разрывы в этих строках и проверил, что там вводятся правильные entitySetNames. - person Matt; 31.10.2009
comment
Если вы развернете представление результатов запроса в визуализаторе отладки, у вас появится свойство Users. Когда вы расширяете это, вы получаете количество пользователей? - person Kim Major; 31.10.2009
comment
Это неверный ответ. Включение принимает имя свойства, а не имя сущности или имя набора сущностей. CreateQuery, OTOH, использует ESQL, который может включать имя набора сущностей, но на самом деле не является именем набора сущностей как таковое. - person Craig Stuntz; 02.11.2009