Entity Framework "Код, который должен быть недоступен" в выражении agrigated include - PullRequest
2 голосов
/ 31 мая 2019

First

Я создал это репозиторий GitHub , для которого требуется только F5, чтобы совершить эту ошибку , поэтому вам будет легко попробовать это. Все ссылки в этом вопросе ведут к этому репо.

Поток кода

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

// The included tables I want to control from my controller
Expression<Func<CompanyDto, object>>[] includes = { x => x.Employees, x => x.Cars };

var companyDto2 = await service.GetByIdAsync(1, includes).ConfigureAwait(false);

и затем в моем слое обслуживания Я сопоставляю, что dto включает в мою сущность , и отправляю их в хранилище

var entityIncludes = mapper.Map<Expression<Func<Entity, object>>[]>(includes);

var result = await repository.GetByIdAsync(id, entityIncludes).ConfigureAwait(false);

Ошибка

Когда я запускаю выражения включения в моем хранилище , я получаю следующую ошибку.

"Код должен быть недоступен"

Вот два примера вещей, которые я пробовал, которые выдают эту ошибку.

Первая попытка

Это была попытка с введите описание ссылки здесь

var queryableResultWithIncludes = includes
.Aggregate(dbContext.Set<TEntity>().AsQueryable(),
(current, include) => current.Include(include));

// return the result of the query using the specification's criteria expression
var result = queryableResultWithIncludes.AsEnumerable();

// Here we get "Code supposed to be unreachable"
var neverHappens = result .ToList();

Вторая попытка

// Second attempts
if (includes.Length > 0)
{
    IQueryable<TEntity> set = includes
       .Aggregate<Expression<Func<TEntity, object>>, IQueryable<TEntity>>
       (dbContext.Set<TEntity>(), (current, expression) => current.Include(expression));

    // Here we also get "Code supposed to be unreachable"
    return await set.SingleOrDefaultAsync(s => s.Id == id).ConfigureAwait(false);
}

Резюме

Чего мне не хватает? Я делаю какие-то анти-паттерны? Мне нужен эксперт EF, чтобы сказать мне, пожалуйста: -)

1 Ответ

2 голосов
/ 01 июня 2019

Как я и подозревал, проблема не имеет ничего общего с EF, но недопустимое выражение, полученное при переводе выражения AutoMapper здесь:

var entityIncludes = mapper.Map<Expression<Func<Entity, object>>[]>(includes);

Это можно увидеть, развернув переменную entityIncludes в окне Locals / Watch - вы увидите рассматриваемое исключение для представления отладки или Parameters свойство LambdaExpression.

С учетом вышесказанного проблема вызвана неправильной настройкой AutoMapper, в частности отсутствием AddExpressionMapping(). Вы сделали это для глобальной конфигурации AutoMapper, но ваш код использует внедрение зависимостей, поэтому вам нужно сделать это там, например

Текущее

services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
// Auto Mapper Configurations
AutoMapper.Mapper.Initialize(cfg =>
{
    cfg.DisableConstructorMapping();
    cfg.AddExpressionMapping();
    cfg.AddProfile<CompanyProfile>();
});

Должно быть

services.AddAutoMapper(cfg =>
{
    cfg.DisableConstructorMapping();
    cfg.AddExpressionMapping();    
}, AppDomain.CurrentDomain.GetAssemblies());
...