簡體   English   中英

從存儲庫獲取實體 object 時如何設置它的 ID

[英]How to set Id of Entity object when getting it from Repository

在 DDD 中,當我從存儲庫中獲取實體時,如何對 Id 屬性進行水合? 當我第一次創建實體時(在它持久化之前),我可以在實體的構造函數中生成一個唯一的 id,但是當我從存儲庫中獲取項目時,我已經有了一個 ID? 那么如何設置它,將 Id 傳遞給實體的構造函數感覺不對? 或者它可以嗎?

我沒有使用 ORM。

public interface IPersonRepository
{
    Person GetById(long id);
}

public abstract class Entity
{
   public long Id { get; private set; }

   protected Entity()
   {
      Id = // Generate a unique Id with some algorithm.
   }
}

public sealed class Person : Entity
{
   //...
}

當我第一次創建實體時(在它持久化之前),我可以在實體的構造函數中生成一個唯一的 id ...

這可能不是一個好主意。 非確定性數據(如時間或遠程可變狀態的副本)應輸入到您的域 model。 在實踐中,你經常會僥幸逃脫; 但僅此一點並不能使它成為一個好主意。

通常的答案是存儲庫將獲取信息的持久表示(例如 DTO),並將其交給以構建實體為目的的工廠

因此,實體的身份只是從存儲庫傳遞到工廠的另一條信息。

現在,這里的“工廠”只是另一種生命周期模式; 它可以采用許多不同的forms,包括構造函數的形式。 在這種情況下,標識符通常只是作為參數傳遞給實體。

特別是標識符可能有點奇怪,因為它們通常不表達業務語義。 標識符模式的典型特征是它們是不透明的東西,實際上只支持相等比較。 您的實體幾乎從不查看自己的標識符來確定下一步該做什么。

但是,如果您的實體需要引用其自己的標識符,無論出於何種原因,您通常會在初始化 object 時創建該引用,並從那時起保持不變(換句話說,實體標識符屬性是不可變的引用到一個不可變的值)。

1) 聚合還是實體? 我認為您的問題在 DDD 方面存在一些混淆。 一般來說,您不應該加載實體。 您應該通過聚合根(即實體)加載聚合,該聚合的所有其他實體應自動加載。

來自埃文斯 DDD:

只有 AGGREGATE 根可以直接使用數據庫查詢獲得。 所有其他對象必須通過關聯的遍歷找到。

馬丁·福勒

聚合是數據存儲傳輸的基本元素 - 您請求加載或保存整個聚合。

聚合根

2)如何設置一個ID。 使用不可變屬性是個好主意。 public long Id { get; private set; } public long Id { get; private set; } ,讓我們認為當我們使用不可變 id 時我們正在正確地做事。 現在讓 go 提前並找到正確設置 Id 的可能方法。

  1. 從 class 方法設置 id。 為現有實體(聚合根)設置 id 看起來令人困惑。 我不建議使用此選項。
  2. 從構造函數中設置 id。 為什么不? 您在創建實體(聚合根)期間設置 Id。 來自埃文斯 DDD:

    公共構造函數必須遵循與 FACTORY 相同的規則:它必須是滿足創建的 object 的所有不變量的原子操作。

  3. 工廠。 來自埃文斯 DDD:

    復雜的裝配體,尤其是聚合體,需要工廠

  4. 在反序列化期間設置 id。 是清晰而簡單的方法。 我會選擇這個。 我會將 Id 和其他數據存儲在一起(這是常見做法)。 GetById(long id); 返回在反序列化期間已經設置了IdPerson

暫無
暫無

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

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