개발새발

[Asp.Net] Dapper QueryAsync splitOn Multi mapping 쿼리 데이터 리스트 그룹화 바인딩 본문

개발/Back

[Asp.Net] Dapper QueryAsync splitOn Multi mapping 쿼리 데이터 리스트 그룹화 바인딩

allkites 2024. 4. 8. 08:17

 

Dapper QueryAsync를 사용해서 반환된 데이터를 내가 원하는 형태로 바인딩하려 했다

[Detail, Contact:[1,2,3]]

Detail 데이터에 Contact 영역을 그룹화하는 방식이다.

 

예시)

public class Info
{
    [Key]
    public int Id { get; set; }
    public string CaseId { get; set; }
    public string State { get; set; }
    public string City { get; set; }
    public string Street { get; set; }
    public List<Contact> ContactInfo { get; set; }
}

public class Contact
{
    [Key]
    public int ContactId { get; set; }
    public string CaseId { get; set; }
    public string Type { get; set; }
}

데이터는 info데이터 + contact데이터 형태로 multi 행으로 들어왔다

그래서 contactid 기준으로 spliton을 하고, 그 이후 데이터를 contactInfo라는 칼럼에 넣으려고 했다

var result = await _conn.QueryAsync<Detail, Contact, Detail>(
    "Select_Detail",
    (info, contact) =>
    {
        info.Contact ??= new List<Contact>();
        info.Contact.Add(contact); 
        return info;
    },
    new { caseId },
    commandType: CommandType.StoredProcedure,
    splitOn: "contactId"
);

Query Multi-Mapping (One to Many)

이렇게 하면 Detail 클래스에 해당하는 값이 리스트 형태로 반환된다.

원하는 형태는 1개의 Detail값에 Contact가 리스트 형태로 출력되는 코드다.

데이터 형태 [{Detail, Contact:[1]}, {Detail, Contact:[2]}, {Detail, Contact:[3]}]

원하는 형태 [Detail, Contact:[1,2,3]]

 

 

해결)

아래처럼 Tuple로 구성하면 원하는 형태로 나온다.

var result = await _conn.QueryAsync<Detail, Contact, Tuple<Detail, Contact>>(
     "Select_Detail",
     (info, contact) => Tuple.Create(info, contact),
     new { caseId },
     commandType: CommandType.StoredProcedure,
     splitOn: "contactId"
 );

var groupedResult = result
    .GroupBy(tuple => tuple.Item1.CaseId)
    .Select(group => new Detail
    {
        id = group.First().Item1.id,
        CaseId = group.Key,
        State = group.First().Item1.State,
        City = group.First().Item1.City,
        Street = group.First().Item1.Street,
        ContactInfo = group
            .Select(item => new CSRContact
            {
                ContactId = item.Item2.ContactId,
                CaseId = item.Item2.CaseId,
                Type = item.Item2.Type,
            }).ToList()
    })
    .ToList();

 

Comments