Asp. Net Ядро / Ядро Entity Framework - System.Linq.Enumerable + SelectEnumerableIterator`2 [MyClass, System.String] - PullRequest
0 голосов
/ 05 августа 2020

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

1023 * результат:

[
{
"registeredYear": "System.Linq.Enumerable+SelectEnumerableIterator`2[MyPath.Groups.GroupYear,System.String]"
}
]

Конечная точка api

public async Task<ActionResult<IEnumerable<UserGroup>>> GetUserGroupYears(string email, string groupName)
    {
        var groupYears = await _repo.GetUserGroupYears(email, groupName);
        var mappedEntities = _mapper.Map<GroupYearsListDto[]>(groupYears);
        return Ok(mappedEntities);
    }

Метод репозитория

public async Task<IEnumerable<UserGroup>> GetUserGroupYears(string email, string groupName)
{
    var userGroupYears = _context.UserGroups
                          .Include(uo => uo.Group.GroupYears)
                            .ThenInclude( oy => oy.Year)
                          .Where(uo => uo.Group.Name == groupName && uo.Email == email );
            return await userGoupYears.ToArrayAsync();
}

Используемые классы:

public class UserGroup
{
    public string Email { get; set; }
    
    public string UserId { get; set; }
    public virtual User User { get; set; }
    
    public string GroupId { get; set; }
    public virtual Group Group { get; set; }
}

public class Group
{
    public string Name { get; set; }
    public virtual ICollection<UserGroup> Users { get; set; }
    public virtual ICollection<GroupYear> GroupYears { get; }
}

public class GroupYear    {
    public string GroupId { get; set; }
    public virtual Group Group { get; set; }

    public string YearId { get; set; }
    public virtual Year Year { get; set; }
    public string RegisteredYear { get; set; }
}

Объект передачи данных и отображение:

public class GroupYearsListDto
{
    public string RegisteredYear { get; set; }
}
public CoreMappingProfiles()
{
    CreateMap<UserGroup, GroupYearsListDto>()
      .ForMember(
          dest => dest.RegisteredYear,
          opt => opt.MapFrom(src => src.Group.GroupYears.Select(x => x.RegisteredYear))
          );                  
}

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

var mappedEntities = _mapper.Map<GroupYearsListDto[]>(GroupYears);

1 Ответ

1 голос
/ 05 августа 2020

Вы получаете этот JSON результат:

[
  {
    "registeredYear": "System.Linq.Enumerable+SelectEnumerableIterator`2[MyPath.Groups.GroupYear,System.String]"
  }
]

Потому что вы сопоставляете IEnumerable<string> с string, как я упоминал в своем комментарии. По сути, вы получаете то же самое, что:

CreateMap<UserGroup, GroupYearsListDto>()
    .ForMember(
        dest => dest.RegisteredYear,
        opt => opt.MapFrom(src =>
        {
            IEnumerable<string> registeredYears = src.Group.GroupYears.Select(x => x.RegisteredYear);
            return registeredYears.ToString();
        })
    );

И registeredYears.ToString() это "System.Linq.Enumerable+SelectEnumerableIterator`2[MyPath.Groups.GroupYear,System.String]".

Я полагаю, вы получите либо:

  1. Только иметь one - так что сделайте что-то вроде: src.Group.GroupYears.Select(x => x.RegisteredYear).Single()
  2. Имейте кратные - так сделайте что-нибудь вроде: string.Join(", ", src.Group.GroupYears.Select(x => x.RegisteredYear))

У вас есть много вариантов, но вам нужно вернуть string в это свойство, иначе вы просто получите ToString() версию IEnumerable<string>.

ОБНОВЛЕНИЕ:

Основываясь на ваших комментариях ниже, вы можете попробовать это :

Репозиторий:

public IQueryable<GroupYear> GetGroupYears(string email, string groupName)
{
    return _context
        .UserGroups
        .Where(x => x.Group.Name == groupName && x.Email == email)
        .SelectMany(x => x.Group.GroupYears);
}

Контроллер:

public async Task<ActionResult<GroupYearsListDto[]>> GetGroupYears(string email, string groupName)
{
    var groupYears = _repo.GetGroupYears(email, groupName);
    var projection = _mapper.ProjectTo<GroupYearsListDto>(groupYears)
    var mappedEntities = await projection.ToArrayAsync();
    return Ok(mappedEntities);
}

Профиль:

CreateMap<GroupYears, GroupYearsListDto>();
...