16

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レベルで並べ替えることは可能ですか?

4

2 に答える 2

16

このシナリオをサポートするためにAutoMapperソースコードを変更することになりました。提案された修正が受け入れられることを願っていますが、それまでの間、詳細は次の場所で確認できます。-

https://github.com/AutoMapper/AutoMapper/pull/327

于 2013-04-22T15:55:36.730 に答える
0

マッピング中にQueryable内のバーを並べ替えるのがこれを行うのに最適な場所であるかどうか疑問に思いますか?マップに並べ替えを配置するということは、不適切なタイミングで並べ替えることを意味しませんか?

たとえば、Barsコレクションに1つのアイテムが含まれているかどうかを知りたい場合はどうでしょうか。呼び出し FooDto.Bars.Any()ても、データベースでソートが発生します。

おそらく、FooDTOに次のような別のプロパティ(マッピングでは無視されます)がある方がよいでしょう。

    public IEnumerable<BarDto> SortedBars
    {
        get
        {
            if (Bars == null)
                return null;

            return Bars.OrderBy(x => x.SortOrder).ToList();
        }
    }
于 2013-04-12T16:00:31.497 に答える