簡體   English   中英

使用AutoMapper從數據庫加載實體?

[英]Using AutoMapper to load entities from the database?

我所讀的大部分內容(例如, 來自作者 )都表明應使用AutoMapper將實體映射到DTO。 它不應從數據庫加載任何內容。

但是如果我有這個怎么辦:

public class Customer {
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<Order> Orders { get; set; }
}

public class CustomerDto {
  public int Id { get; set; }
  public string Name { get; set; }
  public IEnumerable<int> OrderIds { get; set; }   // here is the problem
}

我需要從DTO映射到實體 (即,從CustomerDtoCustomer ),但是首先我必須使用該外鍵列表從數據庫中加載相應的實體。 AutoMapper可以使用自定義轉換器來實現

我同意這感覺不對...但是有哪些替代方案? 將該邏輯放入控制器,服務,存儲庫和某些管理器類中? 所有這些似乎都將邏輯推到了同一層中的其他地方。 如果這樣做,我還必須手動執行映射!

從DDD的角度來看,DTO不應是域的一部分。 因此,AutoMapper也不屬於該域,因為它知道該DTO。 因此,AutoMapper與控制器,服務等位於同一層。

那么,將DTO到實體邏輯(包括訪問數據庫,並可能引發異常)放入AutoMapper映射是否有意義?

編輯
@ChrisSimon在下面的出色回答從DDD角度解釋了為什么我不應該這樣做。 從非DDD角度來看,是否有令人信服的理由不使用AutoMapper從數據庫加載?

首先,我將總結我對DDD中實體的理解:

  1. 可以創建實體-通常使用工廠。 這是他們生命周期的開始。
  2. 可以通過在實體上調用方法來對實體進行突變-修改其狀態。 這就是他們在生命周期中的進步方式。 通過確保實體擁有自己的狀態,並且只能通過調用其方法來修改其狀態,控制實體狀態的邏輯全部在實體類之內,從而使業務邏輯與可維護性更高的系統更加清晰地分離。

使用Automapper從Dto轉換為實體意味着該實體正在放棄對其狀態的所有權。 如果dto處於無效狀態,而您直接將其映射到實體,則該實體可能最終處於無效狀態-您已經失去了使實體包含數據+邏輯的價值,而這是DDD實體的基礎。

為了建議您應該如何實現這一目標,我想問一下-您正在嘗試實現什么操作? DDD鼓勵我們不要考慮CRUD運營,而應該考慮真實的業務流程,並以我們的實體為模型。 在這種情況下,您似乎正在將訂單鏈接到客戶實體。

在應用程序服務中,我將使用類似以下方法:

void LinkOrdersToCustomer(CustomerDto dto)
{
    using (var dbTxn = _txnFactory.NewTransaction())
    {
        var customer = _customerRepository.Get(dto.Id);
        foreach (var orderId in dto.OrderIds)
        {
            var order = _orderRepository.Get(orderId);
            customer.LinkToOrder(order);
        }
        dbTxn.Save();
    }
}

在LinkToOrder方法中,我將具有執行類似操作的顯式邏輯:

  • 檢查訂單不為空
  • 檢查客戶的狀態是否允許添加訂單(他們當前是否處於活動狀態?他們的帳戶是否已關閉?等)
  • 檢查訂單是否確實屬於該客戶(如果由orderId引用的訂單屬於另一個客戶會發生什么?)
  • 詢問訂單(通過訂單實體上的方法)是否處於要添加到客戶的有效狀態。

只有這樣,我才能將其添加到客戶訂單的集合中。

這樣,應用程序“流”和基礎結構管理包含在應用程序/服務層中,而真正的業務邏輯包含在域層中(即您的實體中)。

如果以上要求與您的應用程序無關,則您可能還有其他要求。 如果沒有,那么也許就沒有必要采用DDD的路線-盡管DDD有很多要添加的地方,但其開銷通常僅在具有許多復雜業務邏輯的系統中才值得。

這與您提出的問題無關,但我也建議您研究一下“客戶和訂單”的建模。 它們都是獨立的集合體嗎? 如果是這樣,將客戶建模為包含訂單集合可能會導致一系列問題-當客戶擁有一百萬個訂單時會發生什么? 即使該集合是延遲加載的,您也知道某些時候會嘗試加載它,從而提高性能。 這里有一些有關聚合設計的好書: http : //dddcommunity.org/library/vernon_2011/ ,建議使用ID而不是參考來建模參考。 在你的情況,你可以有OrderIds的集合,甚至可能是一個完全新的實體,以代表的聯系- CustomerOrderLink這將有兩個屬性-客戶編號和的OrderId。 這樣,您的任何實體都將沒有嵌入式集合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM