0

일반적으로 nHibernate를 사용하여 내 엔티티의 고유 ID를 생성하지만 코드로 생성하려고합니다. 다음 예를 고려해보십시오. (내가 잘못한 일을하는 경우 DDD를 처음 사용하는 경우이를 지적하십시오.)새로운 GUID를 사용하여 자식 엔티티를 생성하는 집계 루트

이들은 모두 동일한 어셈블리, 즉 도메인 모델에 속하는 클래스입니다.

public interface AggregateRootState 
{ 
    bool CanAddChild(); 
    bool CanModifyChild(); 
    bool CanDeleteChild(); 
} 

public class AggregateRoot 
{ 
    private AggregateRootState aggregateRootState; 

    public IList<ChildEntity> ChildEntityList {get; internal set;} 

    public bool CanAddChild() 
    { 
     return aggregateRootState.CanAddChild(); 
    } 

    public void AddChild(ChildEntityParameters childEntityParameters) 
    { 
     if (!CanAddChild()) 
      throw new NotImplementedException("aggregate root not in correct state."); 

     ChildFactory.CreateChildEntity(childEntityParameters); 
    } 

    public bool CanModifyChild() 
    { 
     return aggregateRootState.CanModifyChild(); 
    } 

    public void ModifyChild(ChildEntityParameters childEntityParameters) 
    { 

     if (!CanModifyChild()) 
      throw new NotImplementedException("aggregate root not in correct state."); 

     ChildEntity childEntity = ChildEntityList.First(c => c.Id == childEntityParameters.Id); 
     childEntity.Property1 = childEntityParameters.Property1; 
     childEntity.Property2 = childEntityParameters.Property2; 
    } 

    public bool CanDeleteChild() 
    { 
     return aggregateRootState.CanDeleteChild(); 
    } 

    public void DeleteChild(Guid Id) 
    { 
     if (!CanDeleteChild()) 
      throw new NotImplementedException("aggregate root not in correct state"); 

     ChildEntityList.Remove(ChildEntityList.First(c => c.Id == Id)); 
    } 

    public void Validate() 
    { 
     //code to validate the object and ensure it is in a savable state. 
    } 
} 

public class ChildEntityParameters 
{ 
    public Guid Id {get; set;} 
    public string Property1 {get; set;} 
    public string Property2 {get; set;} 
} 

public class ChildEntity 
{ 
    internal ChildEntity() { } 
    public Guid Id {get; set;} 
    public string Property1 {get; internal set;} 
    public string Property2 {get; internal set;} 
} 

internal static class ChildFactory 
{ 
    public static void CreateChildEntity(ChildEntityParameters childEntityParameters) 
    { 
     ChildEntity childEntity = new ChildEntity(); 
     childEntity.Property1 = childEntityParameters.Property1; 
     childEntity.Property2 = childEntityParameters.Property2; 
    } 
} 

내 서비스 레이어는 다음과 같이 보일 것입니다 :

//for simplicity I have arguments rather than using the request/response pattern. 
public class ServiceLayer 
{ 
    public void AddChildEntity(Guid aggregateRootId, string string1, string string2) 
    { 
     AggregateRoot aggregateRoot = aggregateRootRepository.FindBy(aggregateRootId); 
     ChildEntityParameters childEntityParameters = new ChildEntityParameters(); 
     childEntityParameters.Property1 = string1; 
     childEntityParameters.Property2 = string2; 
     aggregateRoot.AddChild(childEntityParameters); 
     aggregateRoot.Validate(); //will throw exception if there is something wrong. 
     aggregateRootRepository.Save(aggregateRoot); 
    } 
} 

지금이 모든 것이 잘 좋은 작동합니다. 그러나 새로 생성 된 ChildEntity의 ID를 프리젠 테이션 레이어로 반환하려면 어떻게해야할까요? 현재로서는 불가능합니다. 전체 객체 그래프를 반환해야합니다. 내가 생각할 수있는 유일한 대안은 내 코드를 다음과 같이 변경하는 것입니다.

internal static class ChildFactory 
{ 
    public static void CreateChildEntity(ChildEntityParameters childEntityParameters) 
    { 
     ChildEntity childEntity = new ChildEntity(); 
     **childEntity.Id = Guid.NewGuid();** 
     childEntity.Property1 = childEntityParameters.Property1; 
     childEntity.Property2 = childEntityParameters.Property2; 
    } 
} 

public class ServiceLayer 
{ 
    public **Guid** AddChildEntity(Guid aggregateRootId, string string1, string string2) 
    { 
     **Guid Id;** 
     AggregateRoot aggregateRoot = aggregateRootRepository.FindBy(aggregateRootId); 
     ChildEntityParameters childEntityParameters = new ChildEntityParameters(); 
     childEntityParameters.Property1 = string1; 
     childEntityParameters.Property2 = string2; 
     **Id = aggregateRoot.AddChild(childEntityParameters);** 
     aggregateRoot.Validate(); //will throw exception if there is something wrong. 
     aggregateRootRepository.Save(aggregateRoot); 
     return Id; 
    } 
} 

이것이 잘못된 것입니까? 아니면 완벽하게 괜찮습니까? 누군가가 명확히 할 수 있다면 좋을 것입니다!

답변

0

이것은 결국 내 해결책이었습니다. save가 실행되면 자식 객체에 대한 ID가 채워집니다. Child 객체에 대한 참조가 있으므로 ID를 반환 할 수 있습니다. DDD에 새가되는 난 당신이 자식 개체 주위에 전달할 수 있다는 것을 알고하지 않았다 ...하지만 에릭 에반스에서 다음과 같은 규칙을 발견 몇 가지 추가 읽기를 수행 한 후 :

루트 엔티티는 내부 참조를 손으로 수 ENTITIES를 다른 오브젝트에 추가하지만 해당 오브젝트는 일시적으로 만 사용할 수 있으며 참조에 보유 할 수 없습니다.

public class ServiceLayer 
{ 
    public **Guid** AddChildEntity(Guid aggregateRootId, string string1, string string2) 
    { 
     **ChildObject obj;** 
     AggregateRoot aggregateRoot = aggregateRootRepository.FindBy(aggregateRootId); 
     ChildEntityParameters childEntityParameters = new ChildEntityParameters(); 
     childEntityParameters.Property1 = string1; 
     childEntityParameters.Property2 = string2; 
     **obj = aggregateRoot.AddChild(childEntityParameters);** 
     aggregateRoot.Validate(); //will throw exception if there is something wrong. 
     aggregateRootRepository.Save(aggregateRoot); 
     return obj.Id; 
    } 
} 
1

Vaughn Vernon의 우수한 book은 엔티티를 만들기위한 적절한 전략이 과도 상태에서 생성되는 것과는 정반대로 완전히 형성된다는 것을 제안합니다. 따라서 아이디로 아이가 만들어내는 것을 보장함으로써 옳은 길에 있다고 생각합니다.

또한 임시 객체의 해시 코드를 가져 오는 것이 항상 동일한 지속 객체에 대해 동일한 해시 코드를 반환하지는 않는 까다로운 문제를 해결합니다.

+0

나는 꽤 공정한 비트를 참조 할 것 같은 그 책을 조사해야합니다. 그래서 내 개체에 대해 개체를 만들 때 ID를 생성해야한다고 제안하는 중입니까? 집계 루트를 포함하여? 원본 질문을 게시 한 후 추가 조사를 수행하여 ID를 지정하면 nHibernate가 레코드를 삽입하거나 업데이트할지 여부를 알 수 없음을 발견했습니다. 이것은 nhibernate의 구성을 변경하는 문제일까요? –

+0

NH가'Save()'를 통해 당신에게 ID를 생성하도록 요청할 수 있습니까? 또는 id = assigned가되도록 매핑을 변경 하시겠습니까? –

+0

나는 혼란 스럽다. NH가 저에게 Save()를 통해 ID를 생성하게되면 새로 생성 된 하위 엔티티의 ID를 가져올 수 없다는 원래 문제로 돌아갑니다. 그래서 나는 id = assigned가되도록 매핑을 변경해야한다고 생각합니다. 이 문제는 여기에 언급 된 바와 같이 있습니다 : http://stackoverflow.com/questions/5048728/fluent-nhibernate-generated-and-assigned-id-columns 그러나 나는 대안을 정말로 보지 못합니까? 나쁜 디자인 결정 : http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-id-assigned –