Dapper : 매핑 계층 구조와 단일 다른 속성

.net c# dapper

문제

나는 Dapper의 단순함과 가능성을 정말 좋아합니다. Dapper를 사용하여 일상적으로 직면하는 공통적 인 문제를 해결하고 싶습니다. 아래에 설명되어 있습니다.

여기 내 간단한 모델입니다.

public class OrderItem {
    public long Id { get; set; }
    public Item Item { get; set; }
    public Vendor Vendor { get; set; }
    public Money PurchasePrice { get; set; }
    public Money SellingPrice { get; set; }
}

public class Item
{
    public long Id { get; set; }
    public string Title { get; set; }
    public Category Category { get; set; }
}

public class Category
{
    public long Id { get; set; }
    public string Title { get; set; }
    public long? CategoryId { get; set; }
}

public class Vendor
{
    public long Id { get; set; }
    public string Title { get; set; }
    public Money Balance { get; set; }
    public string SyncValue { get; set; }
}

public struct Money
{
    public string Currency { get; set; }
    public double Amount { get; set; }
}

두 가지 도전이 저를 곤두박질 쳤습니다.

질문 1 : 속성 차이가 있거나 간단한 enum / struct 매핑이있는 경우 DTO-Entity간에 매핑 논리가있는 DTO를 항상 만들어야합니까?

예를 들면 : 구조체Balance 속성을 가진 내 공급 업체 엔티티가 있습니다 (그렇지 않으면 열거 형일 수 있음). 그 해결책보다 나은 것을 찾지 못했습니다.

public async Task<Vendor> Load(long id) {
    const string query = @"
        select * from [dbo].[Vendor] where [Id] = @id
    ";

    var row = (await this._db.QueryAsync<LoadVendorRow>(query, new {id})).FirstOrDefault();
    if (row == null) {
        return null;
    }

    return row.Map();
}

이 방법에서는 2 개의 오버 헤드 코드가 있습니다. 1. DTO 객체로 LoadVendorRow 를 만들어야합니다. 2. LoadVendorRowVendor 간에 자체 매핑을 작성해야합니다.

public static class VendorMapper {
    public static Vendor Map(this LoadVendorRow row) {
        return new Vendor {
            Id = row.Id,
            Title = row.Title,
            Balance = new Money() {Amount = row.Balance, Currency = "RUR"},
            SyncValue = row.SyncValue
        };
    }
}

아마도 금액과 통화를 함께 저장하고 _db.QueryAsync<Vendor, Money, Vendor>(...) 처럼 검색해야한다고 제안 할 수 있습니다. 아마도, 맞습니다. 이 경우 Enum ( OrderStatus 속성)을 저장 / 검색해야하는 경우 어떻게해야합니까?

var order = new Order
{
    Id = row.Id,
    ExternalOrderId = row.ExternalOrderId,
    CustomerFullName = row.CustomerFullName,
    CustomerAddress = row.CustomerAddress,
    CustomerPhone = row.CustomerPhone,
    Note = row.Note,
    CreatedAtUtc = row.CreatedAtUtc,
    DeliveryPrice = row.DeliveryPrice.ToMoney(),
    OrderStatus = EnumExtensions.ParseEnum<OrderStatus>(row.OrderStatus)
};

나 자신의 구현없이이 작업을 수행하고 시간을 절약 할 수 있을까요?

질문 2 : 간단한 단일 레벨 DTO보다 약간 더 복잡한 엔티티로 데이터를 복원하려면 어떻게해야합니까? OrderItem 은 아름다운 예입니다. 지금 당장 검색하는 방법은 다음과 같습니다.

public async Task<IList<OrderItem>> Load(long orderId) {
    const string query = @"
            select [oi].*,
                   [i].*,
                   [v].*,
                   [c].*
              from [dbo].[OrderItem] [oi]
              join [dbo].[Item] [i]
                on [oi].[ItemId] = [i].[Id]
              join [dbo].[Category] [c]
                on [i].[CategoryId] = [c].[Id]
              join [dbo].[Vendor] [v]
                on [oi].[VendorId] = [v].[Id]
             where [oi].[OrderId] = @orderId
    ";

    var rows = (await this._db.QueryAsync<LoadOrderItemRow, LoadItemRow, LoadVendorRow, LoadCategoryRow, OrderItem>(query, this.Map, new { orderId }));

    return rows.ToList();
}

당신이 볼 수 있듯이, 내 질문 1 문제는 내가 계층 구조의 모든 엔티티에 대한 사용자 지정 매퍼와 DTO를 작성하도록 강요합니다. 그게 내 매퍼 야.

private OrderItem Map(LoadOrderItemRow row, LoadItemRow item, LoadVendorRow vendor, LoadCategoryRow category) {
    return new OrderItem {
        Id = row.Id,
        Item = item.Map(category),
        Vendor = vendor.Map(),
        PurchasePrice = row.PurchasePrice.ToMoney(),
        SellingPrice = row.SellingPrice.ToMoney()
    };
}

불필요한 작업을 방지하기 위해 제거하고 싶은 맵퍼가 많이 있습니다.

인기 답변

납품업자, 품목, 종류와 같은 관계되는 재산을 가진 주문 실재물을 retrive &지도로 나타내는 명확한 방법 있는가?

Order 엔티티를 표시하지는 않지만 OrderItem 을 예로 들어 특정 문제에 대해 (인용 된대로) 맵핑 도구가 필요 없다는 것을 보여줄 것이다. 다음을 수행하여 OrderItem 을 각각의 Item W Vendor 정보와 함 2 검색 할 수 있습니다.

var sql = @"
select oi.*, i.*, v.* 
from OrderItem 
    inner join Item i on i.Id = oi.ItemId
    left join Vendor v on v.Id = oi.VendorId
    left join Category c on c.Id = i.CategoryId";
var items = connection.Query<OrderItem, Item, Vendor, Category, OrderItem>(sql, 
    (oi,i,v,c)=>
    {
      oi.Item=i;oi.Item.Category=c;oi.Vendor=v;
      oi.Vendor.Balance = new Money { Amount = v.Amount, Currency = v.Currency};
      return oi; 
    });

참고 : left join 사용하여 테이블 구조에 따라 적절하게 조정하십시오.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.