หลังจากลองทำ 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 เพื่อมาศึกษา และประยุกต์ใช้ง่ายได้ครับ ^___^
Reference
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.