2012-11-30 75 views
0

酷軟件建築師想要:)如何編程只與子實體創建的域實體

我有兩個實體:公司和用戶。

當用戶被添加到公司時,創建員工實體。員工代表用戶和公司之間的鏈接。沒有訪問列表的員工實體是無用的。換句話說,我有一些不變的:父實體(Employee)必須創建與子(訪問列表)。

我正在尋找desing解決方案來實現這個不變在C#代碼。

僱員實體具有所需參數的構造函數:

public class Employee 
{ 
    public Employee(EmployeeCreationParams creationParams) 
    { 
     this.Company = creationParams.Company; 
     this.User = creationCommand.User; 
    } 

    public Company { get; protected set; } 

    public User { get; protected set; } 

    // other state and logic 
} 

實體Child:

public class EmployeeAccessList 
{ 
    public EmployeeAccessList(EmployeeAccessListCreationParams creationParams) 
    { /* initialization logic */ } 

    public Employee { get; protected set; } 

    public OperationEnum Operation { get; protected set; } 
} 

有通用庫服務:

public class Repository 
{ 
    public void Persist<TEntity>(TEntity entity) 
    { 
     // internal stuff 
    } 
} 

員工被創建,然後堅持:

var employee = new Employee(creationParams); 

_repository.Persist(employee); 

和ACL得到堅持,以及:

var accessList = CreateAccessList(); 

foreach(var acl in accessList) 
{ 
    _repository.Persist(acl); 
} 

我找不到注入的員工創建邏輯訪問列表創建登錄正確的方式。因此,父母和孩子都會成爲一個單位。

我嘗試添加子創建邏輯到父母的構造函數:

public class Employee 
{ 
    public Employee(EmployeeCreationParams creationParams) 
    { 
     this.Company = creationParams.Company; 
     this.User = creationCommand.User; 

     var accessList = CreateAccessList(); 

     foreach(var acl in accessList) 
     { 
      _repository.Persist(acl); 
     } 
    } 
} 

..但這個解決方案看起來不正確的。子對象在父實體之前被持久化。

回答

3

我想你試圖在太少的對象中適合大量不同的事物。那麼當您創建一個僱員之間的3個獨立的責任區分:

  • 員工實例邏輯,換句話說newing了員工和所有相關實體。這是應用程序不可知的,應該在域圖層中定義。由於員工創建看起來有點複雜,Factory可能是該作業的一個好候選人,而不是臃腫的Employee構造函數。

  • 員工持續存在。這屬於基礎架構層,在您的ORM和存儲庫實施中。在保存員工時,利用DDD中的Aggregate和ORM的概念來自動保留聚合中的所有實體(包括AccessLists)是一個好主意。

  • 決定何時保存新員工。這是特定於應用程序的,可以在創建該員工的用例結束時在您的應用程序層服務中執行。

+1

對於工廠建議+1,並引用了DDD Aggregate概念。 – tallseth

+0

謝謝!對我來說,唯一困難的部分是知道聚合根實體的存儲庫(自動保留聚合中的所有實體)。你能否指導我解釋一下這個存儲庫想法和實現的一些資源(如果可能,使用實體框架)。 – Jekas

+0

我不是EF專家,但我想這是在您調用SaveChanges()時由更改跟蹤器(ObjectContext/DBContext)處理的。有許多可能的Repository實現 - 其中有一個必須調用的顯式Save()方法來保存實體,當您添加()實體時內部調用SaveChanges(),另一些則沒有保存邏輯,將其留給他們的消費者決定何時保存。重要的是,Repository實現有一個對ORM變更跟蹤器/會話/對象池的引用,以便他們可以從中查詢,添加到它等。 – guillaume31

1

這是怎麼回事?

public class Employee 
{ 
    public Employee(EmployeeCreationParams creationParams, EmployeeAccessList accessList) 
    { 
     this.Company = creationParams.Company; 
     this.User = creationCommand.User; 
     this.Access = accessList 
    } 
} 

public class Repository 
{ 
    public void Persist<TEntity>(TEntity entity) 
    { 
     // encapsulate the fact that ACLs are stored in a separate way than Employees 
    } 
} 

然後,您將獲得訪問權作爲公司 - 用戶關係的一部分,這是有道理的。作爲實現細節,您可能希望將它們存儲在單獨的表中,但Repository<Employee>的客戶端不需要關心這一點,並且可以稍後更改該實現細節而不更改這些客戶端。您還可以控制這兩個數據庫調用的事務性,而不會將事務性實現暴露給Repository客戶端。

+0

有趣的是,你建議讓訪問列表成爲父實體狀態的一部分。並且在保存父實體時使用Repository的一些實現,子實體也會保存。我會嘗試這種方法。謝謝! – Jekas

+0

很高興幫助@Jekas。 – tallseth

1

這是一個相當「經典」的混合有界上下文的情況。你有一個身份和訪問控制BC,你有一個僱員BC(或者你的案例中有意義的人力資源,組織等)。在你的員工中有一個UserId是可以的,但是你可能比通過在你的員工BC中包含一個用戶對象更加困難。儘管有一個用戶價值對象是可以的。

希望有所幫助。

+0

感謝您的提示! – Jekas