2016-08-09 5 views
2

私は正しく、次をマップするクエリを実行しよう:3レベルのディープマッピングでDapperでマルチマッピングクエリを作成するにはどうすればよいですか?

public class A 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int BId {get; set; } 
    public List<B> { get; set; } 
} 

public class B 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int CId { get; set; } 
    public int DId { get; set; } 
    public C C { get; set; } 
    public D D { get; set; } 
} 

public class C 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class D 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

どのように私はCで正しくエンティティBのリストを持つエンティティAをマッピングし、Dが満たされたクエリを書くのですか?

答えて

1

ここで2つのクエリを実行して、AのBの1対多の性質を取得したいとします。また、BのクエリでAの参照が必要になる可能性があります。

var query1 = conn.Query<A>(select * from dbo.A) 

var query2 = conn.Query<B,C,D,B>("select * from dbo.B...join C...join 

D",(b,c,d)=>{ 



    b.C = c; 
     b.D = d; 

return b; 

     } 

今、あなたはそれらを一緒に配線する必要があります。私はlinq結合と拡張機能を使ってそれを自動化していますが、要点はそれぞれの 'A'をループして、照会2から一致するBを見つけることです。辞書とリストは 'Where'節よりも速いかもしれない下のループを最適化する拡張を書くことができます。

foreach(var a in query1){ 
a.Bs = query2.Where(w=>w.AId.Equals(a.Id)); 
} 

あなたが複数のレコードセットを返すためにQueryMultipleを使用してDBへの旅行を減らすことができます(はずあなたのDBのサポート)。

+0

ハム、私は明日それを試してみます。 1つのクエリでそれを行うことはできませんか? – GustavoAndrade

+0

あなたは1つのクエリでそれを行うことができますし、その後でグループ化します。私はそれが2つでもっと好きで、クエリ2ではAへの完全なマップを実行しません。必要に応じてquery2を返すWithDetailsというパラメータを持つこともできます。つまり、テーブルのクエリ(例:リストページ)と詳細クエリが1つあります。 – BlackjacketMack

+0

最後の1つのコメント...あなたはおそらく完全なquery2.Aをマッピングする必要はありません.Query.BにAidがある限り、それをquery1.A.AIdまで一致させることができます。副次的な点ですが、それによってquery2でその結合を行う必要がなくなり、返される列の数が減ります...どちらも良いことです。私はそれを明確にするために私の応答を更新するつもりです。 – BlackjacketMack

0

Drapper(Dapperの上に構築されています)を使用して、dbへの1回のラウンドトリップでおそらく達成できます。

select * from [TableA]; 
select * from [TableB]; 
select * from [TableC]; 
select * from [TableD] 

...それぞれの結果が他の人に識別子/外部キーのいくつかのフォームを持って、あなたはおそらくのようなリポジトリを構築することができます:あなたは複数の結果を返すSQLクエリのセットを持っていると仮定すると

以下のいずれかの構文が少しオフにすることができるように

public class Repository : IRepository 
{ 
    // IDbCommander is a Drapper construct. 
    private readonly IDbCommander _commander; 

    public Repository(IDbCommander commander) 
    { 
     _commander = commander; 
    } 

    public IEnumerable<A> RetrieveAll() 
    { 
     // execute the multiple queries and 
     // pass control to a mapping function. 
     return _commander.Query(Map.Results); 
    } 

    private static class Map 
    { 
     internal static Func<IEnumerable<A>, 
          IEnumerable<B>, 
          IEnumerable<C>, 
          IEnumerable<C>, 
          IEnumerable<A>> Results = (collectionA, collectionB, collectionC, collectionD) => 
     { 
      // map C and D to B based on their Id's 
      collectionB.C = collectionC.SingleOrDefault(c => c.Id == b.Id); 
      collectionB.D = collectionD.SingleOrDefault(d => d.Id == b.Id); 

      // now map B to A. 
      collectionA.B = collectionB.Where(b => b.Id == a.Id).ToList(); 
      return collectionA; 
     } 
    } 
} 

例は、メモリから入力されたが、あなたはその要旨を取得します。

私はBlackjacetMackに同意します。結果には何らかの形式のページネーションが必要です(Drapperでもサポートされています)。

関連する問題