けさらんぱさらん

方向性は定めず、ただ思いつくままに

Dapper.Netで1対多のマッピングができるのか

前回の記事で1対多のマッピングができなかったのでリベンジ。
結果は、リベンジ失敗です。
Dapperだけの機能だと出来なそうな感じです。
一応、自前でマッピングしてみたのでそれだけ書いておきます。


まず自前でマッピングするのでQueryメソッドは型指定でなくdynamicバージョンでいきます。
dynamicバージョンだと自前でクラスにマッピングする必要があるので
まずマッピングするクラスにコンストラクタを追加します。

public class Group
{
  public long GroupID { get; set; }
  public string GroupName { get; set; }
  public List<Member> Members { get; set; }

  public Group( dynamic rec )
  {
    GroupID = rec.ID;
    GroupName = rec.NAME;

    Members = new List<Member>();
  }
}

public class Member
{
  public long MemberID { get; set; }
  public string MemberName { get; set; }
  public long GroupID { get; set; }
  public Group Group { get; set; }

  public Member( dynamic rec )
  {
    MemberID = rec.MEMBER_ID;
    MemberName = rec.MEMBER_NAME;
    GroupID = rec.GROUP_ID;
  }
}

コンストラクタでdynamicを引数にとって各プロパティにマッピングします。
これで準備はOK
後は実際に取得します。

var sql = "select g.ID, g.Name," +
    "m.MEMBER_ID, m.MEMBER_NAME, m.GROUP_ID" +
    " from GROUPS g inner join MEMBER m on g.ID = m.GROUP_ID" +
    " where g.ID = :id";

var group2 = db.Query( sql, new { id = ids } ).OrderBy( x => x.ID);

List<Group> glist = new List<Group>();
var prevId = -1L;

foreach( var g in group2 )
{
  if( prevId != g.ID )
  {
    glist.Add( new Group( g ) );
  }

  if( glist.Count != 0 )
  {
    glist.Last().Members.Add( new Member( g ) );
  }

  prevId = g.ID
}

foreach( var g in glist )
{
  Console.WriteLine( g.GroupID + "|" + g.GroupName );
  g.Members.ForEach( m => Console.WriteLine( m.MemberName ) );
}

自前でマッピングするのでSQLはすっきりしますね
その後は、ループ回しながら1対多の関係を作っていきます。
このループがLINQでかけると良かったんですが、自分にはそこまでLINQの腕が無く断念しました。
どなたかLINQで書けるのであればそっと教えてほしいです。