У меня есть граф объектов, который я загружаю из базы данных, используя EF CodeFirst и AutoMapper в DTO: -
public class Foo
{
public int Id { get; set; }
public virtual ICollection<Bar> Bars { get; set; }
}
public class Bar
{
public int Id { get; set; }
public int FooId { get; set; }
public virtual Foo Foo { get; set; }
public string Name { get; set; }
public int SortOrder { get; set; }
}
public class FooDto
{
public IEnumerable<BarDto> Bars { get; set; }
}
public class BarDto
{
public string Name { get; set; }
public int SortOrder { get; set; }
}
Мои сопоставления выглядят так: -
mapper.CreateMap<Foo, FooDto>();
mapper.CreateMap<Bar, BarDto>();
До сих пор так хорошо. Я могу захватить сущности из моего контекста и выполнить проект в DTO: -
var foos = context.Foos.Project().To<FooDto>();
То, что я не могу сделать с этим подходом, однако, сортирует Bars
по их SortOrder
внутри IQueryable.
Если я попробую: -
mapper.CreateMap<Foo, FooDto>()
.ForMember(
x => x.Bars
opt => opt.MapFrom(src => src.Bars.OrderBy(x => x.SortOrder)));
mapper.CreateMap<Bar, BarDto>();
var foos = context.Foos.Project().To<FooDto>();
Я получаю исключение: -
System.InvalidOperationException: Sequence contains no elements
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at AutoMapper.MappingEngine.CreateMapExpression(Type typeIn, Type typeOut)
...
Похоже, это связано с https://github.com/AutoMapper/AutoMapper/issues/159 - хотя я уже использую сложный тип для дочерней коллекции. Я думаю, что CreateMapExpression не поддерживает OrderBy в дочерних коллекциях?
Если я не использую .Project(). Для() я могу легко сортировать дочернюю коллекцию: -
var model = context.Foos.Select(x => new FooDto()
{
Bars = x.Bars.OrderBy(y => y.SortOrder)
});
но затем мне нужно повторить отображение везде, где я хочу его использовать, победив цель использования AutoMapper.
Любопытно: -
1) Я могу выполнять другие (более сложные?) операции над дочерней коллекцией и сглаживать их в моем родительском DTO без проблем: -
mapper.CreateMap<Foo, FooDto>()
.ForMember(
x => x.AllBarsHaveAName,
opt => opt.MapFrom(src =>
src.Bars.All(x => x.Name != null)));
2) Я могу Mapper.Map<FooDto>(foo);
в памяти просто отлично, и он не сортирует бары без проблем.
Можно сортировать дочернюю коллекцию на уровне IQueryable при использовании .Project(). To()?