2009-12-10 4 views
1

다음 상황이 발생했습니다.재귀 삭제를 구현하는 방법은 무엇입니까?

고객은 프로젝트 및 프로젝트에 라이센스가 포함되어 있습니다. 좋습니다 때문에 우리는 아무것도 삭제하지 않지만 우리는 대신 IsDeleted를 사용합니다. 기타 캐스케이드 삭제를 사용했을 수 있습니다. 내가

customerRepository.Delete(customer); 

를 호출하지만, 여기에 문제를 시작 있도록

Owkay 나는 저장소 패턴으로 작동합니다. 고객은 true로 설정됩니다. 그러나 그 고객의 모든 프로젝트를 삭제하고 싶습니다. 그리고 삭제 된 각 프로젝트는 모든 라이센스를 삭제해야합니다.

이 경우 적절한 해결책이 있는지 알고 싶습니다. 그래도 공연해야합니다.

실제 문제의 단순한 버전임을 유의하십시오. 고객은 또한 라이센스에 링크 된 사이트도 가지고 있지만 문제를 단순화하고자했습니다.

SQL Server 2008을 데이터베이스로 사용하는 C# 환경에서 작업하고 있습니다.

편집 : 나는

답변

1

난 그냥 같이 보일 것이 논리를 캡슐화하는 저장 프로 시저 (또는 저장 프로 시저의 그룹)를 작성하는 것이 좋습니다 :

update Customer set isDeleted = 1 
where CustomerId = @CustomerId 

/* Say the Address table has a foreign key to customer */ 
update Address set isDeleted = 1 
where CustomerId = @CustomerId 

/* 
    To delete related records that also have child data, 
    write and call other procedures to handle the details 
*/ 
exec DeleteProjectByCustomer(@CustomerId) 

/* ... etc ... */ 

그런 다음 트랜잭션 내에서 customerRepository.Delete에서이 프로 시저를 호출합니다.

2

하나의 옵션은 트리거를 사용하여 데이터베이스에서이 작업을 수행하는 것입니다 데이터베이스에 연결할 ENTERPRICE 라이브러리를 사용하고 있습니다. 다른 옵션은 계단식 업데이트를 사용하는 것이 겠지만 도메인 작동 방식에 맞지 않을 수도 있습니다.

개인적으로 나는 글 머리 기호를 쓰고 C# 코드를 써서 IsDeleted 유형 필드를 설정해 주었다. (DB에 액세스하는 앱이 하나뿐이라면).

+0

예, 트리거가 위험하다고 생각합니다. 당신은 그들을 추적 할 수 있습니다. – user29964

+0

예. 사람들은 때때로 트리거가 생성되었음을 "잊어 버리는"경우가 있습니다. – RichardOD

+0

개인적으로 필자는 레코드가 설정 될 때마다 삭제되고 적절한 다른 변경이 이루어 지도록 트리거 아이디어를 좋아합니다. 나는 이것이 애플리케이션 코드를 통해 무책임하다고 생각한다. 데이터 무결성 문제가 발생할 위험이 있습니다. 우연히 누군가 삭제 된 경우 모든 하위 레코드를 통해 삭제 취소를 설정할 수도 있습니다. – HLGEM

0

이것은 전적으로 귀하의 DAL에 따라 다릅니다. 예를 들어 NHibernate 매핑은 추가 코드없이 이러한 모든 관련 객체를 계단식으로 삭제하도록 설정할 수 있습니다. 나는 EF가 비슷한 것을 가지고있을 것이라고 확신한다. DB에 어떻게 연결하고 있습니까?

개체가 유지되지 않으면 .NET GC는 참조가 없으면 모든 프로젝트 개체를 제거합니다. 나는 당신의 질문에서 당신이 데이터베이스에서 그들을 제거하는 것에 대해 이야기하고 있다고 생각합니까?

0

관계가 고정되어있는 경우 (즉, 라이센스가 항상 프로젝트와 관련이 있고 프로젝트가 고객과 관련된 경우), 업데이트를 계단식으로 연결하지 않아도됩니다.

SELECT [...] FROM License l 
JOIN Project p ON l.ProjectID = p.ID 
JOIN Customer c on p.CustomerID = c.ID 
WHERE l.IsDeleted <> 1 AND p.IsDeleted <> 1 AND c.IsDeleted <> 1 

이것은 단지 당신이 질문이 경우 성능 부담을 추가합니다 : 이미 쿼리 부드러운 삭제의 고통을 다루고 있기 때문에, 당신은뿐만 아니라 계층 구조를 확인하는 고통에 추가 할 수 있습니다 조상 테이블에 조인하지 않는 하위 테이블

계단식 접근법에 비해 추가 장점이 있습니다. 항목을 자동으로 삭제 취소하지 않고 항목의 삭제를 취소 할 수 있습니다.프로젝트 라이센스 중 하나를 삭제 한 다음 프로젝트를 삭제 한 다음 프로젝트의 삭제를 취소하면 계단식 접근 방식으로 첫 번째 라이센스를 삭제한다는 사실을 잃게됩니다. 이 접근법은 그렇지 않습니다. 실제로 데이터베이스에 개인 _IsDeleted 값을 저장하기 위해주의해야하지만 ...

private bool _IsDeleted; 
public bool IsDeleted 
{ 
    get 
    { 
     return _IsDeleted || (Parent == null) ? false : Parent.IsDeleted; 
    } 
    set 
    { 
     _IsDeleted = value; 
    } 
} 

, 그리고 IsDeleted의 값이 아닌 : 개체 모델에서

, 당신은 이런 식으로 구현 것입니다.

+0

네, 한 레벨 가져 오기를 위해이 작업이 완료되었지만 2-3 레벨이 내려간 경우에는 한 항목 만로드하면됩니다. – user29964

관련 문제