Automapper сообщает, что отсутствует карта из System.Строка в System.Char? Но я не вижу свойства Char

#c# #automapper

#c# #automapper

Вопрос:

У меня есть три класса:

 public class UserReport : Entity
{
    public string Name { get; set; }
    public string Email { get; set; }
    public List<string> Departments { get; set; }
    public List<string> Titles { get; set; }
}

public abstract class Entity
{
    public Guid Id { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateLastModified { get; set; }
    public string CreatedBy { get; set; }
    public string LastModifiedBy { get; set; }
    public bool Active { get; set; }

    protected Entity()
    {
        DateCreated = DateTime.Now;
        DateLastModified = DateTime.Now;
        Id = Guid.NewGuid();
    }
}

public class UserModel
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Departments { get; set; }
    public string Titles { get; set; }
}
  

С моими настройками automapper, установленными как:

 CreateMap<List<string>, string>().ConvertUsing(strings => {
            if (strings != null)
                return string.Join("n", strings);
            return "";
        });
CreateMap<UserReport, UserModel>();
  

При попытке вызова из универсального метода с использованием расширений Automapper Ef:

 IQueryable<TModel> modelQueryable = _reportService.GetReportBaseQuery().ProjectToQueryable<TModel>();
  

Я получаю эту ошибку

Отсутствует карта из системы.Строка в System.Char. Создайте с помощью Mapper.Создайте карту.

GetReportBaseQuery() возвращает IQueryable<TReport> , поэтому UserReport в данном случае. Я не вижу никаких char свойств, почему это происходит?

Просто для тестирования я попытался создать его:

 CreateMap<String, Char>().ConvertUsing(x => x.FirstOrDefault());
  

И затем он говорит:

Типы аргументов не совпадают

Дальнейшие исследования показывают, что это работает:

 Mapper.Map<List<TReport>, List<TModel>>(_reportService.GetReportBaseQuery().ToList());
  

Но я не могу использовать это, так как мне нужно, чтобы оно возвращалось с запросом. Итак, что-то меняется, когда я пытаюсь выполнить проекцию EF, хотя не уверен, что это такое. Написать оператор select от одного к другому достаточно просто, но это не универсально и не может быть использовано повторно.

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

1. Можете ли вы попробовать это: CreateMap<UserReport, UserModel>().ForMember(x => x.Departments, o => o.MapFrom(s => string.Join("n", s.Departments))).ForMember(x => x.Titles, o => o.MapFrom(s => string.Join("n", s.Titles))); ? У меня есть гипотеза, но я не уверен, правильно ли это

2. Откуда .ProjectToQueryable<TModel>() берется? Я установил AutoMapper. EF6 Nuget, но не может его найти, и кажется, что это ключ к воспроизведению ошибки

3. @JakubJankowski вы должны иметь возможность добавлять using AutoMapper.QueryableExtensions; , а затем вы должны увидеть расширение ProjectToQueryable Кстати, я воссоздавал проблему и попробовал ваше предложение, и, похоже, оно исправляет отображение, мне интересно, обрабатывает ли Automapper каждую строку в List<string> виде списка символов и ищет сопоставление для них

4. Да, оглядываясь назад, я уже знал эту проблему: LINQ to Entities does not recognize the method 'System.String Join(System.String, System.Collections.Generic.IEnumerable 1 [System. String])’метод, и этот метод не может быть преобразован в выражение хранилища. `

5. Ну, я только что нашел метод и воспроизвел вашу ошибку. Действительно, расширения обрабатывают string как набор символов, а List<string> — как набор строк, таким образом пытаясь сопоставить: string => char . Должен ли я создать ответ из своих комментариев?

Ответ №1:

Решение состоит в том, чтобы явно установить сопоставление для полей Departments и Titles :

 CreateMap<UserReport, UserModel>()
    .ForMember(x => x.Departments, o => o.MapFrom(s => string.Join("n", s.Departments)))
    .ForMember(x => x.Titles, o => o.MapFrom(s => string.Join("n", s.Titles)));
  

Но это не объясняет, почему возникает такая ситуация.
Как указал ДОТанг:

LINQ to Entities не распознает метод ‘System.Соединение строк (System.Строка, Система.Коллекции.Общий.IEnumerable1[System.Метод String])’, и этот метод не может быть преобразован в выражение хранилища.

Расширение AutoMapper, похоже, пытается отобразить следующую вещь:

 IEnumerable<string> => IEnumerable<char>