Включение дочерних объектов в Entityframework

#entity-framework #linq-to-entities #iqueryable

#entity-framework #linq-to-entities #iqueryable

Вопрос:

Я хочу включить дочерние объекты в список IQueryable..

Я хочу включить дочерний объект в выбранные столбцы некоторого списка таблиц типа IQueryable..

Я пытался вот так:

 IQueryable<Persons> persons = Context.Persons.Select(x=> new persons{Pkid=x.pkid, FirstName=x.FirstName}).AsQueryable();

persons= persons.Include("Address");
  

это включение дочерних объектов не работает .. кто-нибудь, пожалуйста, помогите … где я делаю неправильно..
большое спасибо…

Ответ №1:

Include не работает с проекцией. Более того, это не требуется. Просто сделайте это:

 var query = context.Persons
                   .Select(x => new PersonDto
                       {
                          Id = x.pkid, 
                          FirstName = x.FirstName,
                          Address = x.Address
                       });
  

Здесь несколько моментов:

  • НЕТ Include
  • Address доступ к которым осуществляется непосредственно в проекции, EF обработает это
  • Я использую PersonDto в качестве цели проекции. PersonDto имеет только Id , FirstName и Address .
  • Вы можете проецировать на пользовательский тип или анонимный тип, но вы не можете проецировать на entity type (сопоставленный тип) — это не работает и выдает исключение.
  • Если вы хотите использовать сопоставленный тип, вы не можете возвращать только выбранные скалярные столбцы — все столбцы всегда будут загружены. Выборочно могут быть загружены только свойства навигации. Чтобы преодолеть это, люди иногда используют разбиение таблицы, но это то, что работает, если вы можете разделить свою большую сущность на непересекающиеся сущности. В вашем сценарии используйте только проекцию.

Ответ №2:

Вы не можете использовать Include() в проекции, попробуйте это:

 Iquerable<Persons> persons = Context.Persons
                                    .Include("Address")
                                    .Select(x=> new persons{Pkid=x.pkid, FirstName=x.FirstName})
                                    .AsQuerable();
  

Также у вас конфликт именования, вы проецируете на тип persons и хотите сохранить результаты в IQueryable именованном persons — один из них неверен. Есть ли причина, по которой вам вообще нужна проекция? Вы могли бы просто сделать

 Iquerable<Persons> persons = Context.Persons.Include("Address");
  

Комментарии:

1. это всего лишь пример .. вот почему я использую persons в обоих местах .. извините за эту ошибку .. мне нужно выполнить проект и выбрать всего несколько столбцов.. потому что в моем проекте я должен включить одну из моих таблиц, в которой содержится 100 columns..it для обработки этих результатов требуется слишком много времени (.ToList())… более того, я буду использовать только 5 столбцов из этих результатов .. мне не нужны эти 95 столбцов в этой таблице.. Я не могу изменить структуру БД и ее базу данных 5-летней давности .. Могу ли я включить прогнозируемый результат … спасибо за ваш ответ…

2. @Sunny: Нет, вы не можете выполнить Include() над прогнозируемым результатом, но и Select() , и Include() работают в БД, поэтому предложенные выше изменения должны сработать для вас, это приведет к SQL-запросу, в котором будут выбраны только нужные вам столбцы.

3. @Sunny: BrokenGlass говорит именно то, что я говорил в своем посте. Также опубликован пример взломанного стекла. Просто добавьте любые столбцы, которые вам нравятся, из объекта Address в проектируемый объект.

4. Спасибо за ваши ответы .. но я получаю эту ошибку Сущность или сложный тип ‘tablename’ не может быть сконструирован в запросе LINQ to Entities.. Я всегда получаю эту ошибку, когда когда-либо делаю select (новый тип таблицы ..) для результатов..

5. @Sunny: вы не должны проецировать на объект, который вы должны либо проецировать на анонимный тип, либо на пользовательский класс POCO, который содержит только нужные вам свойства.

Ответ №3:

Сначала: проверьте, включена ли отложенная загрузка или нет. Я испытал разные результаты, когда это было включено. Я предпочитаю, чтобы отложенная загрузка была отключена.

Второе: проверьте этот синтаксис:

 result = (From person In context.Persons.Include("Address")).ToList();
  

Постскриптум: Полезные советы и рекомендации по EF : http://blogs.msdn.com/b/alexj/archive/2009/03/26/index-of-tips.aspx

Обновить:

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

Проверьте это:

 result = (From person In context.Persons.Include("Address") Select New With {.FirstName = item.FirstName, .AddressValue = item.Address.Value}).ToList();
  

Комментарии:

1. Я хочу включить прогнозируемый результат.. Я не хочу получать все столбцы в своей таблице .. у меня есть таблица, в которой слишком много столбцов (например, 100) .. и . ToList() требует слишком много времени для обработки всех этих результатов.. спасибо за ваш ответ..

2. @Sunny: Пожалуйста, проверьте обновление, которое я добавил к своему сообщению, и прокомментируйте, как оно работало.