[nhibernate] NHibernate에서 자식 개체를 삭제하는 방법은 무엇입니까?

자식 개체의 IList와 일대 다 관계를 갖는 부모 개체가 있습니다. 자식 개체를 삭제하는 가장 좋은 방법은 무엇입니까? 부모를 삭제하지 않습니다. 내 부모 개체에는 자식 개체의 IList가 포함되어 있습니다. 다음은 일대 다 관계에 대한 매핑입니다.

<bag name="Tiers" cascade="all">
  <key column="mismatch_id_no" />
  <one-to-many class="TGR_BL.PromoTier,TGR_BL"/>
</bag>

clear ()를 사용하여 컬렉션에서 모든 개체를 제거한 다음 SaveOrUpdate ()를 호출하면 다음 예외가 발생합니다.

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column

자식 개체를 개별적으로 삭제 한 다음 부모에서 제거하려고하면 예외가 발생합니다.

deleted object would be re-saved by cascade

NHibernate에서 자식 개체를 삭제하는 것은 이번이 처음입니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

편집 : 명확히하기 위해-부모 개체를 삭제하려는 것이 아니라 자식 개체 만 삭제하려고합니다. 나는 부모의 일대 다 관계를 설정했습니다. 하위 개체 매핑에 대해 다 대일 관계도 만들어야합니까?



답변

컬렉션에서 항목을 제거 할 때 NHibernate의 기본 작동 모드는 단순히 연결을 끊는 것이기 때문에 첫 번째 오류가 발생합니다. 데이터베이스에서 NHibernate는 자식 행의 외래 키 열을 null로 설정하려고합니다. 해당 열에 null을 허용하지 않기 때문에 SQL Server에서 오류가 발생합니다. 컬렉션을 지운다 고해서 반드시 자식 개체가 삭제되는 것은 아니지만이를 수행하는 한 가지 방법은 cascade = all-delete-orphan을 설정하는 것입니다. 이는 NHibernate에게 외래 키 열을 설정하는 대신 새로 분리 된 행을 삭제해야 함을 알려줍니다.

SaveOrUpdate NHibernate를 호출하면 먼저 모든 자식 개체를 삭제하기 때문에 두 번째 오류가 발생합니다. 그런 다음 어느 관계도 역으로 표시되지 않기 때문에 NHibernate는 자식 테이블의 외래 키 열을 null로 설정하려고 시도합니다. 행이 이미 삭제되었으므로 두 번째 오류가 발생합니다. 이 문제를 해결하려면 관계의 한쪽에 inverse = true를 설정해야합니다. 이는 일반적으로 하나 (기본 키 또는 상위) 측에서 수행됩니다. 이렇게하지 않으면 NHibernate가 관계의 각 측면에 대해 적절한 업데이트를 수행합니다. 불행히도 두 개의 업데이트를 실행하는 것은 적절한 작업이 아닙니다.

관계의 한 쪽을 항상 반대쪽으로 표시해야합니다. 코딩 방법에 따라 계단식을 사용해야 할 수도 있고 필요하지 않을 수도 있습니다. Clear ()를 사용하여 원샷 삭제를 활용하려면 캐스케이드를 정의해야합니다.


답변

Chuck의 답변에 따르면 부모 측 매핑에 Inverse = true를 추가하여 문제를 해결했습니다.

메시지에 많은 MessageSentTo가 있습니다.

[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)]
public IList<MessageSentTo> MessageSendTos
{
    get { return m_MessageSendTo; }
    set { m_MessageSendTo = value; }
}

Castle ActiveRecord를 사용하고 있습니다. 척 감사합니다.


답변

saveOrUpdate () 대신 merge ()를 사용해보십시오. 또한 캐스케이드가 all-delete-orphan으로 설정되어 있고 부모-자식 관계가 반전 가능한지 확인하십시오 (부모에서 inverse = true이고 not-null = true 인 부모 ID 인 자식의 필드). .


답변

이 예에는 제품이 nullable이 아닌 많은 제품이있는 카테고리가 있습니다.

플러시 전에 제품을 삭제하고 상위 컬렉션에서 제거하여 문제를 해결할 수 있지만 더 나은 해결책을 찾고 있습니다.

product = pRepo.GetByID(newProduct.ProductID);
product.Category.Products.Remove(product);
pRepo.Delete(product);

어쨌든 도움이되기를 바랍니다.


답변

계단식 속성 값을 “all”에서 “all-delete-orphan”으로 변경합니다.


답변

문제를 일으키는 열의 매핑에서 Not-Null = true를 설정하십시오. 그래도 정확한 구문이 확실하지 않습니다 (죄송합니다).


답변