c# - 텍스트 - messagebox 예제




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

나는 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 사용하여 테이블 구조에 따라 적절하게 조정하십시오.


100 % 질문을 이해할 수 있는지 잘 모르겠습니다. 그리고 아무도 그것을 아직 시도하지 않았다는 사실은 제가 혼란스럽지 않을 때 혼자가 아니라고 믿게합니다.

당신은 Dapper의 기능을 좋아한다고 언급하지만, 당신이 예제에서 그것을 사용하는 것을 보지 못합니다. Dapper의 대안을 개발하고 싶습니까? 또는 Dapper를 코드에서 사용하는 방법을 모른다는 것입니까?

어쨌든 다음은 귀하의 검토를 위해 Dapper의 코드 기반에 대한 링크입니다 : https://github.com/StackExchange/dapper-dot-net

귀하의 질문을 명확히 할 수 있기를 바랍니다. 귀하의 회신을 기다리고 있습니다.







dapper