EF: жадно включать одно поле - PullRequest
0 голосов
/ 07 мая 2018

В моей базе данных есть Object, в котором есть объект Owner. Owner имеет строку Name. Object также содержит объект Details.

Мне нужны Object, это Details и Owner.Name. Я хочу запретить загрузку всего объекта Owner (как детализировано здесь ), и мне нужен только один запрос к базе данных.

Я пытался:

DataContext.Objects.Select(o => new { Object = o, OwnerName= o.Owner.Name })
           .Include(o => o.Object.Details);

но бросает:

System.InvalidOperationException: 'Тип результата запроса не является ни EntityType, ни CollectionType с типом элемента сущности. Путь «Включить» может быть указан только для запроса с одним из этих типов результатов.

Также пытался позвонить Include до Select:

var d = DataContext.Objects.Include(o => o.Details)
.Select(o => new { Object = o, OwnerName= o.Owner.Name });

Но это игнорирует Include, т.е. Доступ к d.Details вызывает запрос к БД.

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Вы касаетесь проблемы, которая существует в EF.

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

Include влияет на это поведение, сообщая EF также включает указанное навигационное свойство (со всеми его скалярными свойствами)

Но тогда мы доберемся до Select. Когда вы используете это, вы, по сути, даете фиксированный список столбцов, которые вы хотите получить. Это переопределяет поведение по умолчанию при загрузке всех скалярных свойств, что, к сожалению, также переопределяет добавленные вами операторы Include.


Самым простым решением является явное указание EF получить подробности:

var d = DataContext.Objects.Include(o => o.Details)
    .Select(o => new { 
               Object = o, 
               ObjectDetails = o.Details,
               OwnerName= o.Owner.Name 
    });

Кроме того, поскольку Select явно указывает, какие столбцы EF необходимо извлечь, вам больше не нужен оператор Include.

Это поведение уже можно увидеть, когда вы извлекаете o.Owner.Name без фактического вызова Include(o => o.Owner).

0 голосов
/ 07 мая 2018

Это должно сделать (хотя Details загружается в отдельное свойство для исправления комментария @ Flatter):

DataContext.Objects
           .Include(o => o.Owner>)
           .Include(o => o.Details)
           .Select(o => new {Object = o, 
                             OwnerName = o.Owner.Name,
                             Details = o.Details});

Возвращает новый object с Object, установленным на выбранный Object (рассмотрите возможность переименования этого, если возможно, это очень запутанно), и OwnerName, заполненный из таблицы владельца, без загрузки всего владельца. Он также заполняет Details как отдельное свойство, поскольку Select игнорирует Include.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...