2017-05-15 12 views
0

複雑なオブジェクトを2つの内部結合を持つクエリの結果にマップしたいとします。 1つの内部結合をマッピングするソリューションがあることはわかっていますが、2つの内部結合をマッピングする必要があります。ここでDapper map multiple joins Sqlクエリ

はシナリオです:

私のクラスは以下のとおりです。

public class Order 
{ 
    public int id { get; set; } 
    public string order_reference { get; set; } 
    public string order_status { get; set; } 
    public List<OrderLine> OrderLines { get; set; } 
} 

public class OrderLine 
{ 
    public int id { get; set; } 
    public int order_id { get; set; } 
    public string product_number { get; set; } 
    public List<OrderLineSize> OrderLineSizes { get; set; } 
} 

public class OrderLineSize 
{ 
    public int id { get; set; } 
    public int order_line_id { get; set; } 
    public string size_name { get; set; } 
} 

注文はリストとしてOrderLineSizesとして一覧やオーダーラインとして注文ラインを持っています。

さて、ここでは私のクエリベースは、私が正しいデータでList<Order>を移入したいことである:

SELECT * 
FROM orders_mstr o 
INNER JOIN order_lines ol ON o.id = ol.order_id 
INNER JOIN order_line_size_relations ols ON ol.id = ols.order_line_id 

ここで私はこれまで試したものです。これを使用して

var lookup = new Dictionary<int, Order>(); 
      connection.Query<Order, OrderLine, Order>(@" 
        SELECT o.*, ol.* 
        FROM orders_mstr o 
        INNER JOIN order_lines ol ON o.id = ol.order_id      
        ", (o, ol) => { 
        Order orderDetail; 
        if (!lookup.TryGetValue(o.id, out orderDetail)) 
        { 
         lookup.Add(o.id, orderDetail = o); 
        } 
        if (orderDetail.OrderLines == null) 
         orderDetail.OrderLines = new List<OrderLine>(); 
        orderDetail.OrderLines.Add(ol); 
        return orderDetail; 
       }).AsQueryable(); 

      var resultList = lookup.Values; 

、私はオーダーオブジェクトをOrderLineと正常にマッピングできますが、OrderLineSizesにも正しいデータを設定したいと思います。

答えて

0

クラス「OrderDetail」は何を提供していないのかわからないので、Orderクラスを使用しました。
これはQueryMultipleでも行うことができますが、あなたの質問にはINNER JOINが含まれているので使用しません。

public Dictionary<int, Order> GetOrderLookup() 
{ 
    var lookup = new Dictionary<int, Order>(); 

    const string sql = @" SELECT o.id, 
            o.order_reference, 
            o.order_status, 

            ol.id, 
            ol.order_id, 
            ol.product_number, 

            ols.id, 
            ols.order_line_id, 
            ols.size_name 
          FROM orders_mstr o 
          JOIN order_lines ol ON o.id = ol.order_id 
          JOIN order_line_size_relations ols ON ol.id = ols.order_line_id"; 

    List<Order> orders = null; 
    using (var connection = OpenConnection(_connectionString)) 
    { 
     orders = connection.Query<Order, OrderLine, OrderLineSize, Order>(sql, (order, orderLine, orderLizeSize) => 
     { 
      orderLine.OrderLineSizes = new List<OrderLineSize> { orderLizeSize }; 
      order.OrderLines = new List<OrderLine>() { orderLine }; 
      return order; 
     }, 
     null, commandType: CommandType.Text).ToList(); 
    } 

    if (orders == null || orders.Count == 0) 
    { 
     return lookup; 
    } 

    foreach (var order in orders) 
    { 
     var contians = lookup.ContainsKey(order.id); 
     if (contians) 
     { 
      var newLinesToAdd = new List<OrderLine>(); 
      var existsLines = lookup[order.id].OrderLines; 
      foreach (var existsLine in existsLines) 
      { 
       foreach (var newLine in order.OrderLines) 
       { 
        if (existsLine.id == newLine.id) 
        { 
         existsLine.OrderLineSizes.AddRange(newLine.OrderLineSizes); 
        } 
        else 
        { 
         newLinesToAdd.Add(newLine); 
        } 
       } 
      } 
      existsLines.AddRange(newLinesToAdd); 
     } 
     else 
     { 
      lookup.Add(order.id, order); 
     } 
    } 

    return lookup; 
} 
+0

OrderDetailは基本的にオーダークラス – Saadi

+0

です。 –

0

私はベストを尽くして解決しました。ここで

は私ごとなど、より簡単かつ正確なソリューションです。:

var lookup = new Dictionary<int, OrderDetail>(); 
      var lookup2 = new Dictionary<int, OrderLine>(); 
      connection.Query<OrderDetail, OrderLine, OrderLineSize, OrderDetail>(@" 
        SELECT o.*, ol.*, ols.* 
        FROM orders_mstr o 
        INNER JOIN order_lines ol ON o.id = ol.order_id 
        INNER JOIN order_line_size_relations ols ON ol.id = ols.order_line_id   
        ", (o, ol, ols) => 
      { 
       OrderDetail orderDetail; 
       if (!lookup.TryGetValue(o.id, out orderDetail)) 
       { 
        lookup.Add(o.id, orderDetail = o); 
       } 
       OrderLine orderLine; 
       if (!lookup2.TryGetValue(ol.id, out orderLine)) 
       { 
        lookup2.Add(ol.id, orderLine = ol); 
        orderDetail.OrderLines.Add(orderLine); 
       } 
       orderLine.OrderLineSizes.Add(ols); 
       return orderDetail; 
      }).AsQueryable(); 

      var resultList = lookup.Values.ToList(); 
0

私は代を計算するためのビッグデータを取得するためにDapperのを使用することにしました。これは_RepositoryBase.csファイルの3つのテーブルを結合する私の大まかな拡張メソッドです。

public List<Tuple<T, T2, T3, T4>> QueryMultiple<T2, T3, T4>(string sql, object param) 
     where T2 : class 
     where T3 : class 
    { 
     using (var con = new SqlConnection(GetConnStr())) 
     { 
      if (con.State == ConnectionState.Closed) 
       con.Open(); 

      var query = con.Query<T, T2, T3, T4, Tuple<T, T2, T3, T4>>(sql, (t, t2, t3, t4) => Tuple.Create(t, t2, t3, t4), param); 

      //if (query.Count() == 0) 
      // return new List<T>(); 

      var data = query.ToList(); 

      con.Close(); 
      con.Dispose(); 

      return data; 
     } 
    } 

この関数を使用すると、sql結合データをdapper経由で取得できます。

public List<Table1> GetSqlJoinedDataViaDaper(int customerId) 
    { 
     var repo = new GenericRepository<T_LOOKUP>(); 
     var sql = @"select table1.ID Table1ID, table1.*, 
        table2.ID Table2ID, table2.*, 
        table3.ID Table3ID, table3.* 
        from dbo.Table1 table1 (nolock) 
        left outer join dbo.Table2 table2 (nolock) on table2.ID=table1.FKTable2ID 
        left outer join dbo.Table3 table3 (nolock) on table3.ID=table1.FKTable3ID 
        where [email protected] "; 

     var resultWithJoin = repo.QueryMultiple<Table1, Table2, Table3>(sql, 
      new { p1 = 1, splitOn = "Table1ID,Table2ID,Table3ID" }).ToList(); 

     var retval = new List<Table1>(); 
     foreach (var item in resultWithJoin) 
     { 
      Table1 t1 = item.Item2; //After first split 
      t1.Table2 = item.Item3; //After Table2ID split 
      t1.Table3 = item.Item4; //After Table3ID split 

      retval.Add(t1); 
     } 
     return retval; 
    } 

要約: 選択してテーブル間に分割を挿入します。 Dapperに分割してデータを取得するとします。私はこれを使用し、Entity Frameworkよりもうまく機能しました。