[Dapper] Query Parent-Child อย่างไร ?

หลังจากลองทำ Framework ที่เอา Dapper เป็น ORM ครับ ตอนนี้ก็ติดปัญหาว่า เราจะดึงข้อมูลที่อยู่ในรูปแบบ Parent-Child กันอย่างไรครับ โดยผมมีรายละเอียด ดังนี้

  • โจทย์ที่ผมต้องการ คือ เวลา Query ข้อมูลจาก Table Corporateaction แล้ว ให้มันดึงข้อมูลของ Table ลูก CorporateDetail ขึ้นมาให้หมด โดยการ Query เพียงคร้งเดียวเท่านั้นครับ
  • POCO Class ของผม มีโครงคร่าวๆ ดังนี้ครับ
    • Parent Class
      [Serializable]
      [Table("corporateaction")]
      public class CorporateActionDTO : MasterDTO
      { 
         //CorporateActionDTO  is Parent Class
         private new object Id { get; set; }
         [Key]
         public int CorporateActionId { get { return (int)base.Id; } set { base.Id = (int)value; } }
      
         public int? SecurityId { get; set; }
      
         public string ActionType { get; set; }
      
         public DateTime ExDate { get; set; }
      
         //Many Field ...
         
         //CorporateDetailDTO  is Child Class
         [NotIn]
         public IList<CorporateDetailDTO> CorporateDetails { get; set; }
      }
    • Child Class
      [Serializable]
      [Table("CorporateDetail")]
      public class CorporateDetailDTO : MasterDTO
      {
         //CorporateDetailDTO  is Child Class
         private new object Id { get; set; }
      
         public int? CorporateDetailId { get { return (int?)base.Id; } set { base.Id = (int?)value; } }
      
         public int? CorporateActionId { get; set; }
      
         public string IsExercise { get; set; }
         public int? RightSecurityId { get; set; }
         public decimal MasterSecRatio { get; set; }
         public decimal RightSecRatio { get; set; }
         public decimal RightPrice { get; set; }
         public DateTime TradableDate { get; set; }
      }
  • Query ที่ผมเขียนไว้
    SELECT CA.*, CAD.*
    FROM CORPORATEACTION CA
       INNER JOIN CORPORATEDETAIL CAD
          ON CA.CORPORATEACTIONID = CAD.CORPORATEACTIONID
             AND CA.CREATETIME = CAD.CREATETIME
    WHERE CA.EXDATE = @EXDATE
      AND CA.ACTIVEFLAG = 'A'
  • Code ในส่วนของ Data Access ผมเขียนลักษณะนี้ครับ
    public class CorporateActionADO : MasterADO<CorporateActionDTO, IDictionary<string, object>>, ICorporateActionDAO
    {
       public IList FetchWithAllDetailList(IList pActionTypeList
                                                             , DateTime pExDate
                                                             , IList pParentSecurityList)
       {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(INV_SQL_COMMAND.CORPORATEACTION_FETCHWITHALLDETAIL);
    
            Dictionary<string, object> parameter = new Dictionary<string, object>();
    	parameter.Add("EXDATE", pExDate);
    
            var lookup = new Dictionary<int, CorporateActionDTO>();
            connection.Query<CorporateActionDTO, CorporateDetailDTO, CorporateActionDTO>(sb.ToString()
                      , (CorporateAction, CorporateActionDetail) => {
                            CorporateActionDTO CA;
                            if (!lookup.TryGetValue((int)CorporateAction.Id, out CA))
                            {
                                lookup.Add((int)CorporateAction.Id, CA = CorporateAction);
                            }
                            if (CA.CorporateDetails == null)
                            {
                                CA.CorporateDetails = new List();
                            }
                            CA.CorporateDetails.Add(CorporateActionDetail);
                            return CA;
                        }, parameter, splitOn: "CorporateDetailId").AsQueryable();
            var resultList = lookup.Values;
          	return resultList.ToList();
       }
    }
  • เดี๋ยวมาอธิบาย Code ของ Data Access กันก่อนครับ สังเกตุว่าจริงๆ มันก็ Query มาทั้งหมดครับ แต่ใช้ Feature Data Mapping กับ Dictionary มาช่วยจัด Data ให้อยุ่ใน Format ที่ต้องการครับ

สำหรับ Blog นี้เกิดจากการไปขุด Unit Test ของ Dapper ครับ จาก Dapper/Dapper.Tests/MultiMapTests.cs ซึ่งนั้นหมายความว่า ถ้า Library มีเป็นลักษณะ Open Source ถึงแม้ว่าเราจะไม่เจอคู่มือ แต่เราสามารถไปดู Unit Test เพื่อมาศึกษา และประยุกต์ใช้ง่ายได้ครับ ^___^


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.