2017-10-20 16 views
1

クエリを動作させようとしていますが、試したことがすべてうまくいっていないので、正直なところ、どうすればいいかわかりません。LINQ GroupBy AutoMapperを使用した集約

Person、PersonVote、PersonCategory、Category、City、およびFirstAdminDivisionの合計6つのテーブルを照会します。

PersonVoteは人のユーザーレビューテーブルで、1-5の値を受け入れる小数点以下の桁(Vote)という列が含まれています(5が「最高」です)。 FirstAdminDivisionはカリフォルニア州のような米国の州と同義です。 Personテーブルには、Cityへの外部キーであるCityIdという列があります。私が信じている他のテーブルはほとんど自明なので、必要がない限りコメントはしません。

私の目標は、特定の人物のPersonVoteテーブルのすべての投票の平均に基づく「最も人気のある」人物のリストを返すクエリを作成することです。例えば、ある人が3票を持っていて、3票がすべて「5」であれば、それらはリストの最初のものになります...この時点で二次秩序については本当に気にしません。ネクタイが「勝つ」。

私はAutoMapperを使わないでこの作業をしていますが、ProjectTo拡張メソッドを使用してAMの機能を使用することが大好きです。コードはきれいで読みやすいので、可能ならばその方法を使用したいが、働く

ここで私は動作しています....基本的に、私はこれがLINQのSelectメソッドの代わりにProjectToで可能かどうか確認しようとしています。

List<PersonModel> people = db.People 
        .GroupBy(x => x.PersonId) 
        .Select(x => new PersonModel 
        { 
         PersonId = x.FirstOrDefault().PersonId, 
         Name = x.FirstOrDefault().Name, 
         LocationDisplay = x.FirstOrDefault().City.Name + ", " + x.FirstOrDefault().City.FirstAdminDivision.Name, 
         AverageVote = x.FirstOrDefault().PersonVotes.Average(y => y.Vote), 
         Categories = x.FirstOrDefault().PersonCategories.Select(y => new CategoryModel 
         { 
          CategoryId = y.CategoryId, 
          Name = y.Category.Name 
         }).ToList() 
        }) 
        .OrderByDescending(x => x.AverageVote) 
        .ToList(); 
+0

あなたはhttps://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensionsを試したことがありますか? – abatishchev

+0

ええと、私はドキュメントを見直していくつかの異なるアプローチを試しましたが、実際に動作するものはまだありません。 "IGrouping'2からPersonModelへのマップがありません。Mapper.CreateMap "またはこれを使用して作成: "指定された型メンバー 'AverageVote'はLINQ to Entitiesでサポートされていません"私は両方が何であるか理解していますが、私は後になったことを達成するためにクエリを構造化する方法や、AMのProjectionを使って私が望むものが可能であるかどうかわかりません。 – user1011627

+0

AMなしでEFのみを使用して目的のクエリを構築して実行できましたか? – abatishchev

答えて

3

コードサンプルを見て、あなたのモデルがどのようなものかを判断して、例を設定しました。

public class People 
{ 
    public int PeronId { get; set; } 
    public string Name { get; set; } 
    public City City { get; set; } 
    public IList<PersonVotes> PersonVoes { get; set; } 
} 

public class PersonVotes 
{ 
    public int Vote { get; set; } 
} 

public class City 
{ 
    public string Name { get; set; } 
} 

public class FirstAdminDivision 
{ 
    public string Name { get; set; } 
} 

public class PersonModel 
{ 
    public int PersonId { get; set; } 
    public string Name { get; set; } 
    public string LocationDisplay { get; set; } 
    public double AverageVote { get; set; } 
} 

ProjectTo拡張機能を使用するには、私はその後、初期化静的APIを通じてAM:私は機能だけを表示するプロパティのいくつかを使用して実装

 Mapper.Initialize(cfg => 
     { 
      cfg.CreateMap<IEnumerable<People>, PersonModel>() 
       .ForMember(
        model => model.LocationDisplay, 
        conf => conf.MapFrom(p => p.FirstOrDefault().City.Name)) 
       .ForMember(
        model => model.AverageVote, 
        conf => conf.MapFrom(p => p.FirstOrDefault().PersonVoes.Average(votes => votes.Vote))); 
     }); 

だから、次のオブジェクトを与えられました

var people = new List<People>() 
     { 
      new People 
      { 
       PeronId = 1, 
       City = new City 
       { 
        Name = "XXXX" 
       }, 
       PersonVoes = new List<PersonVotes> 
       { 
        new PersonVotes 
        { 
         Vote = 4 
        }, 
        new PersonVotes 
        { 
         Vote = 3 
        } 
       } 

      } 
     }; 

私が持っているクエリ、その後になります。

var result = people 
      .GroupBy(p => p.PeronId) 
      .Select(peoples => peoples) 
      .AsQueryable() 
      .ProjectTo<PersonModel>(); 

私はメモリオブジェクトを使用していますので、AMでProjectTo拡張メソッドを使用するためにIQueryableに変換しています。

私はこれがあなたが探していたことを望んでいます。乾杯、

は、エンティティクエリにLINQのために更新:

var result = db.People 
    .GroupBy(p => p.PersonId) 
    .ProjectTo<PersonModel>(base.ConfigProvider) // AM requires me to pass Mapping Provider here. 
    .OrderByDescending(x => x.AverageVote) 
    .ToList(); 
+0

おかげさまODawg ...これは正しい軌道に乗った。私は必要な実際のLINQステートメントのLINQ To Entitiesバージョンを含めるように答えを更新しました。私のための鍵はあなたが投稿したAMマッピングにあった。 – user1011627