2012-12-26 6 views
1

나는 두개의 테이블을 가지고 있는데, 한 테이블은 부모 테이블이고 다른 테이블 B는 자식 테이블이다 (1 : N 관계).거래가 자녀 기록을 삭제하는 좋은 방법입니까?

테이블 A에서 부모를 삭제할 때 테이블 B의 하위 레코드를 삭제하려면 데이터베이스에서 삭제할 때 계단식을 사용하지 않으면 다음과 같이하십시오.

  1. 사용자 A 컨텍스트에서 상위 레코드를로드 한 다음 컨텍스트에서 모든 하위 레코드를로드하고 모두 삭제됨으로 표시하십시오.
  2. 다른 사용자는 새로운 어린이를 추가하십시오.
  3. 사용자 A 변경 사항이 저장됩니다. 두 번째 사용자가 추가 한 레지스터가 컨텍스트에 없으므로 참조 무결성 오류가 발생합니다.

이 경우 첫 번째 사용자는 예외가 발생할 때 모든 하위 항목을 다시로드 할 수 있지만 세 번째 사용자는 새 하위 항목을 추가하고 동일한 문제가 발생할 수 있습니다. 이론적으로 이것은 항상 발생할 수 있으며 첫 번째 사용자는 부모를 삭제하지 않을 것입니다.

이러한 이유로, 트랜잭션을 사용하여 작업을 수행하려고합니다.

  1. 첫 번째 사용자가 트랜잭션을 시작합니다.
  2. 첫 번째 사용자 마크가 부모를 삭제하고 변경 사항을 저장합니다. 부모가 데이터베이스에서 차단되었습니다.
  3. 첫 번째 사용자는 삭제 된 것으로 표시된 모든 하위 항목을로드합니다.
  4. 첫 번째 사용자가 변경 사항을 저장합니다. 어린이의 외래 키가 기록이 경우

, I는 의심 상위 레지스터는 제 1 사용자에 의해 차단 될 때,이 상위의 ID는 다른 사용자에 의해 이용 될 수 있는가? 이론적으로 삭제 된 레코드이기 때문에 데이터베이스에서 ID를 사용할 수 없습니까?

데이터베이스에서 ID를 사용할 수없는 경우 부모가 없으므로 두 번째 사용자는 참조 무결성을 위해 새 하위를 추가하려고하면 예외가 발생합니다. 그래서 문제가 해결되었습니다. 다른 일을 할 필요가 없습니다. 부모 삭제 방법에서

: 데이터베이스가 차단 된 부모의 ID를 사용할 수있는 경우

그러나, 내가 두 가지 일을 할 필요가

  1. 로드 부모를, 그것을 표시 삭제 및 변경 사항 저장 이것은 레지스터를 차단합니다.
  2. 어린이를로드하고 삭제 된 것으로 표시하여 변경 사항을 저장합니다.
  3. 트랜잭션을 승인하십시오. 어린이

    1. 로드 부모를 추가하는 방법에

    . if가 차단되면 메서드는 레지스터가 사용 가능할 때까지 대기합니다.

  4. 새 자녀를 추가하십시오.
  5. 변경 내용을 적용하십시오.

자식을 삭제하기 위해 부모를 컨텍스트에로드 할 필요가 없습니다. 데이터베이스에 대한 추가 쿼리 일 수 있습니다.

부모가 없으면 부모가 삭제 되었기 때문에 지금 새 사용자를 추가하려고하는 사용자에게 예외를 요구하지 않습니다.

부모가있는 경우 하위를 추가 할 수 있습니다.

그래서 두 가지 질문이 있습니다.

  1. 는 모든 아이들이 삭제되도록 부모 레코드를 삭제 트랜잭션을 사용하는 것이 좋습니다?

  2. 부모가 차단되었을 때 트랜잭션이 좋은 옵션 인 경우 데이터베이스에서 부모 레코드를 추가하기 위해 상위 ID를 사용하도록 허용하지 않거나 상위 레코드를로드하기 위해 솔루션을 수행해야합니다. 아이들을 지우려고?

+0

부모를 삭제 된 것으로 표시하고 변경 사항을 저장할 수 없습니다. EF는 레코드 삭제를 시도하고 FK 제약 조건을 위반합니다. 또는 데이터베이스 필드에 플래그를 설정하여 삭제 된 것으로 표시합니까? –

+0

내가 잘못하지 않은 경우 트랜잭션에 있거나 부모를 삭제 된 것으로 표시하고 첫 번째 savechanges를 만들면 여전히 트랜잭션을 수용하지 않기 때문에 아무런 문제가 없습니다. 그러나 이것은 이론 상으로는 시험을 치르지 않았습니다. –

답변

1

트랜잭션이 삭제 작업을 연기하지 않습니다. 데이터베이스에 "deleted as marked"와 같은 것이 없습니다. 엔티티를 삭제됨으로 표시하고 SaveChanges을 실행하면 레코드가 데이터베이스에서 삭제됩니다. 거래에서 항상 발생합니다. 레코드가 삭제 되려고하면 FK 제한이 검사되고 종속 레코드가 있으면 오류가 throw됩니다 (제한 조건에 대한 ON DELETE 규칙이 다른 옵션을 정의하지 않는 한). FK 제약 조건을 사용할 때는 항상 부모보다 먼저 자식을 삭제해야합니다.

설명이 정확하다면 가장 먼저 두려워하는 접근 방식을 사용하고 SaveChangesTransactionScope으로 닫으십시오. 직렬화 가능 격리 수준의 트랜잭션을 실행하므로 현재 트랜잭션이 완료 될 때까지 다른 트랜잭션이 잠긴 키 범위에 레코드를 삽입 할 수 없습니다 (쿼리에 의해 잠김).

직렬화 가능 트랜잭션을 사용하는 솔루션이 작동하는 동안 다른 문제 (응용 프로그램에서 다른 트랜잭션과의 교착 상태)가 발생할 수 있습니다. 그 때문에 반복되는 실패한 트랜잭션이 가장 좋은 옵션입니다. 시스템에 큰 동시로드가있어 삭제 트랜잭션이 "항상"실패 할 경우 응용 프로그램을 완전히 다시 설계해야 할 때가 있습니다.

+0

readCommited 대신 트랜잭션 범위의 직렬화 가능 격리 수준? –

+0

그리고 반복되는 실패한 트랜잭션 솔루션을 사용하기로 결정했다면 얼마나 많은 시도가 좋은 숫자입니까? 10, 20, 50 ...? 그리고 데이터베이스의 performarce는 많이 영향을받지 않습니까? –

+0

'TransactionScope '에 직렬화 가능 트랜잭션 수준이 있습니다. 직렬화 가능 트랜잭션은 데이터베이스에 부정적인 영향을 미칩니다. 영향은 트랜잭션에 의해 차단 된 동시 요청 수에 따라 다릅니다. –