2016-03-31 41 views
2

私はこの質問に関連するかなりの数の記事を見直してきましたが、それらの質問/回答のいくつかを私の状況の答えに近づけるために使用しましたが、右。LINQ/AutoMapper Projectを入れ子にしました入れ子にしました

5つのテーブル(Grandparent、GrandparentParent、Parent、ParentChild、Child)を持つEF6コンテキストがあります。 GPテーブルとPCテーブルは、ファミリ階層を結びつけるシンプルな多対多の関係です。

私のビジネス要件は、データベースを照会し、孫のすべてのリストを含む祖父母オブジェクトのリストを返すことです。私はそれに対応するテーブルのサブセットである3のViewModelクラスを持っていると私はGVMが

public class GrandparentViewModel 
{ 
    public int GrandparentId { get; set; } 
    public string Name { get; set; } 

    public List<ChildViewModel> Grandchildren { get; set; } 
} 

私がAutoMapperのProjectTo <を使用していますことに注意することも重要です= GrandparentViewModelクラスのリストにダウンデータベース階層をフラット化したいです>拡張メソッドを使用すると、投影をオフロードでき、各テーブルのフィールドのサブセットのみを選択することができます。つまり、各テーブルにDateOfBirthがあり、クエリやフィールドを返すことはありません。

私はこの作業をしようとして、私はAutoMapperのITypeConverterインターフェイスにつまずいて、そのインターフェイスを実装するクラスを祖父母と子に実装しました。ここでは、これらのクラスは次のとおりです。ここで

public class GrandparentConverter : ITypeConverter<Grandparent, GrandparentViewModel> 
{ 
    public GrandparentViewModel Convert(ResolutionContext context) 
    { 
     var entities = context.SourceValue as Grandparent; 

     return entities 
      .Select(x => new GrandparentViewModel 
      { 
       GrandparentId = x.GrandparentId, 
       Name = x.Name, 
       Grandchildren = AutoMapper.Mapper.Map<IEnumerable<Parent>, List<ChildViewModel>>(x.Parents) 
      }).ToList(); 

     //return new GrandparentViewModel 
     //{ 
     // GrandparentId = entities.GrandparentId, 
     // Name = entities.Name, 
     // Grandchildren = entities.Parents.SelectMany(x => x.Children.Select(y => new ChildViewModel 
     // { 
     //  ChildId = y.ChildId, 
     //  Name = y.Name 
     // }).ToList()).ToList() 
     //}; 
    } 
} 


public class ChildConverter : ITypeConverter<IEnumerable<Parent>, List<ChildViewModel>> 
{ 
    public List<ChildViewModel> Convert(ResolutionContext context) 
    { 
     var entities = context.SourceValue as IEnumerable<Parent>; 

     return entities 
      .SelectMany(x => x.Children) 
      .Select(x => new ChildViewModel 
      { 
       ChildId = x.ChildId, 
       Name = x.Name 
      }).ToList(); 
    } 
} 

がかかりコードは次のとおりです。

MapperConfiguration mapper = new MapperConfiguration(cfg => 
     { 
      cfg.CreateMap<Child, ChildViewModel>(); 
      cfg.CreateMap<IEnumerable<Parent>, List<ChildViewModel>>().ConvertUsing<ChildConverter>(); 

      cfg.CreateMap<Grandparent, GrandparentViewModel>(); 
      cfg.CreateMap<IEnumerable<Grandparent>, List<GrandparentViewModel>>().ConvertUsing<GrandparentConverter>(); 
     }); 

     FamilyEntities db = new FamilyEntities(); 
     List<GrandparentViewModel> entities = db.Set<Grandparent>() 
      .Where(x => x.GrandparentId == 1) 
      .ProjectTo<GrandparentViewModel>(mapper) 
      .ToList(); 

は現在、解決策は(、ビルドを実行し、私が期待するよう特異GrandparentViewModelクラスを返しますが、すべてのフィールドつまり、祖父母の名前(つまり...名前)もnullです)。

私が紛失していることやデータが入力されていない理由についてのアイデアはありますか?私はそのTypeConverterクラスでブレークポイントを設定しようとしましたが、AutoMapperのMapperConfigurationクラスで指定されたマッピング設定だけがそのコンバータを使用していても実行されません。そのCreateMap呼び出しを削除すると、AutoMapperは "Missing configuration"エラーをスローします。

アドバイスをいただければ幸いです。

編集:私はこの問題の縮小版を作成し、AutoMapper MapperConfigurationをビルドしてProjectToメソッドに渡すと、カスタムTypeConverterクラスのブレークポイントがヒットします。したがって、元の記事では、AutoMapperがConvertUsingメソッドで指定されたコンバータを実際に使用していないという問題が発生しているようです。

答えて

0

これはAutoMapperのProjectToロジックのバグです。この問題を解決するにはIssue 1216がAutoMapperに記録されています。その間、私はうまくいくと思われる回避策が与えられました。

cfg.CreateMap<Grandparent, GrandparentViewModel>() 
    .ForMember(d => d.Grandchildren, 
     opt.MapFrom(s => s.Parents.SelectMany(x => x.Children)); 
関連する問題