Je rencontre un problème d'utilisation d'une projection AutoMapper (version 5.1.1) associée à une expression de propriété Linq OrderBy Child. J'utilise Entity Framework Core (version 1.0.0). Je reçois l'erreur suivante:
"doit être un noeud réductible"
Mes objets DTO sont les suivants
public class OrganizationViewModel
{
public virtual int Id { get; set; }
[Display(Name = "Organization Name")]
public virtual string Name { get; set; }
public virtual bool Active { get; set; }
public virtual int OrganizationGroupId { get; set; }
public virtual string OrganizationGroupName { get; set; }
public virtual int StrategyId { get; set; }
public virtual string StrategyName { get; set; }
public virtual OrganizationGroupViewModel OrganizationGroup { get; set; }
}
public class OrganizationGroupViewModel
{
public virtual int Id { get; set; }
[Display(Name = "Organization Group Name")]
public virtual string Name { get; set; }
public virtual bool Active { get; set; }
}
Les modèles d'entité correspondants sont les suivants:
public class Organization
{
public int Id { get; set; }
public string Name { get; set; }
public string TimeZone { get; set; }
public bool Active { get; set; }
//FKs
public int OrganizationGroupId { get; set; }
public int StrategyId { get; set; }
//Navigation
public virtual OrganizationGroup OrganizationGroup { get; set; }
public virtual Strategy Strategy { get; set; }
[JsonIgnore]
public virtual List<AppointmentReminder> AppointmentReminders { get; set; }
}
public class OrganizationGroup
{
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
public virtual List<Organization> Organizations { get; set; }
}
Les profils de mon AutoMapper sont les suivants:
public class OrganizationMapperProfile : Profile
{
public OrganizationMapperProfile()
{
CreateMap<Task<Organization>, Task<OrganizationViewModel>>();
CreateMap<Organization, OrganizationViewModel>()
.ForMember(dest => dest.OrganizationGroupName, opt => opt.MapFrom(src => src.OrganizationGroup.Name));
CreateMap<OrganizationInput, Organization>()
.ForMember(x => x.Id, opt => opt.Ignore());
}
}
public class OrganizationGroupMapperProfile : Profile
{
public OrganizationGroupMapperProfile()
{
CreateMap<Task<OrganizationGroup>, Task<OrganizationGroupViewModel>>();
CreateMap<OrganizationGroup, OrganizationGroupViewModel>();
CreateMap<OrganizationGroupInput, OrganizationGroup>()
.ForMember(x => x.Id, opt => opt.Ignore());
}
}
Lorsque j'exécute les instructions suivantes, je suis en mesure d'exécuter et d'obtenir les résultats des 2 premières instructions:
var tmp = await _context.Organizations.Include(x => x.OrganizationGroup).OrderBy(x => x.OrganizationGroup.Name).ToListAsync();
var tmp4 = await _context.Organizations.Include(x => x.OrganizationGroup).OrderBy("OrganizationGroup.Name").ToListAsync();
Mais lorsque j'ajoute le ProjectTo, l'erreur ci-dessus apparaît:
var tmp5 = await _context.Organizations.Include(x => x.OrganizationGroup).OrderBy(x => x.OrganizationGroup.Name).ProjectTo<OrganizationViewModel>().ToListAsync();
var tmp6 = await _context.Organizations.Include(x => x.OrganizationGroup).OrderBy("OrganizationGroup.Name").ProjectTo<OrganizationViewModel>().ToListAsync();
En tant qu'information supplémentaire, je suis en mesure de OrderBy avec Projections travaillant sur les propriétés de la classe parente, comme
var tmp7 = await _context.Organizations.Include(x => x.OrganizationGroup).OrderBy(x => x.Name).ProjectTo<OrganizationViewModel>().ToListAsync();
var tmp8 = await _context.Organizations.Include(x => x.OrganizationGroup).OrderBy("Name").ProjectTo<OrganizationViewModel>().ToListAsync();
Quelqu'un a-t-il déjà rencontré ce problème? On dirait que j'essaie de faire quelque chose qui n'est pas pris en charge autrement, est-ce intentionnel? Merci pour toute aide / perspicacité.
Il semble que le problème soit causé par la propriété OrganizationGroup
de la classe OrganizationViewModel
- AutoMapper génère un contrôle nul que EF Core n'apprécie pas dans la combinaison avec votre OrderBy
(je suppose qu'un seul des nombreux bogues actuellement dans EF Core). Il peut être facilement reproduit par la requête de projection manuelle suivante:
var tmp5a = _context.Organizations
.OrderBy(x => x.OrganizationGroup.Name)
.Select(e => new OrganizationViewModel
{
Id = e.Id,
OrganizationGroup = e.OrganizationGroup != null ? new OrganizationGroupViewModel
{
Id = e.OrganizationGroup.Id,
Name = e.OrganizationGroup.Name,
Active = e.OrganizationGroup.Active,
} : null,
})
.ToList();
Pour résoudre le problème, configurez AutoMapper pour ne pas générer de contrôle null
pour cette propriété, comme suit:
CreateMap<Organization, OrganizationViewModel>()
.ForMember(dest => dest.OrganizationGroup, opt => opt.AllowNull())
.ForMember(dest => dest.OrganizationGroupName, opt => opt.MapFrom(src => src.OrganizationGroup.Name));