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>();
ただし、このアプローチではできないことは、IQueryable内で並べ替えるBars
ことです。SortOrder
私が試してみると:-
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()。To()を使用していない場合は、子コレクションを簡単に並べ替えることができます。-
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);
メモリ内で問題なく並べ替えることができ、バーを問題なく並べ替えることができます。
.Project()。To()を使用しながら、子コレクションをIQueryableレベルで並べ替えることは可能ですか?