2011-01-27 5 views
1

부모 레코드 하나와 4 개 이상의 자식 레코드를 계층 적 순서로 삽입해야하는 C# 응용 프로그램이 있습니다. IOW, 부모 계약은 하나 이상의 위치에 적용되며 각 위치에는 하나 이상의 항목이 있으며 각 항목에는 하나 이상의 서비스가 있으며 각 서비스에는 하나 이상의 요구 사항이 있습니다. 응용 프로그램은 먼저 각 레코드의 각 테이블 시퀀스에서 하나씩 오라클 시퀀스 번호 집합을 가져옵니다. 어떤 이유로 든 (레거시 데이터베이스) 각 레코드에는 상위 레코드의 시퀀스 번호뿐만 아니라 계약 시퀀스 번호가 있습니다.트랜잭션에 부모/자식 레코드 삽입

따라서 코드는 트랜잭션을 시작하고 부모 수준의 시퀀스 번호가있는 부모를 삽입 한 다음 부모 레코드를 FK로 이미 채운 위치 레코드와 자체 테이블 시퀀스 번호를 삽입하려고 시도합니다. 그러나 부모 번호를 찾을 수 없기 때문에 FK 위반이라는 Oracle-02291 오류가 발생합니다. 나는이 추측하고

INSERT into Contracts (contract_sequence_number, ...) values (10437, ...); 
INSERT into Locations (location_sequence_number, contract_sequence_number, ...) 
    values (23733, 10437, ...); 
... 

는 부모가 최선을 다하고되지 않았기 때문에, 따라서 사용할 수 없습니다. 그러나 부모를 커밋 할 수 없습니다. 자식 레코드 중이 실패하면 자식 삽입 전에 커밋이 종료됩니다.

나는 이것이 일반적인 시나리오라는 것을 안다. 답은 반드시 pre-noob이어야한다. 하지만, 지금까지 발견 한 모든 대답은 부모 시퀀스 번호가 FK를 만족시키기 위해 "테이블에서"발견된다는 것을 의미합니다.

이 문제를 해결하는 방법에 대한 의견을 보내 주시면 대단히 감사하겠습니다.

랜디

+0

삽입을 두 개의 분리 된 기능으로 나눌 수 없습니까? 부모 레코드의 ID를 C# 코드로 반환 한 다음이를 사용하여 자식 삽입을 수행 하시겠습니까? – TheGeekYouNeed

+0

실제로 이들은 동일한 트랜잭션 블록 내에서 두 개의 서로 다른 기능을 수행합니다. 내 문제를 명확히하기 위해 두 SQL 문을 보여주고있다. – EoRaptor013

답변

0

귀하의 의견을 보내 주셔서 감사합니다. 나는 그것이 나쁘다고 생각했다. 두 개의 매우 유사한 스키마가 있고, 내가 사용하고있는 연결에는 두 가지 모두에 대한 액세스 권한이 있습니다. 두 스키마에는 동일한 이름의 테이블이 있습니다. 나에게 명확하지 않은 이유 때문에 부모가 하나의 schmea에 삽입되었지만 자식이 다른 스키마에 삽입하려고 시도하고있었습니다. 물론 그것은 PK/FK 관계를 해결할 수 없습니다!

다시 고맙습니다.

0

는 PRAGMA_AUTONOMOUS_TRANSACTION 설정으로 수행 삽입물의는? 보류중인 커밋을 전체 트랜잭션에서 볼 수 있어야합니다.

다른 생각 - 삽입이 PRE 트리거에 있으면 POST 트리거로 이동해보십시오.

+0

저장 함수가 Oracle Command 개체를 작성하지만 응용 프로그램은 C#입니다. PRAGMA_AUTONOMOUS_TRANSACTION에 대해 읽어야합니다. 그 생각은 순전히 오라클 절차였습니다. – EoRaptor013

+0

PRAGMA는 정상적인 것이 아니지만 그것이 존재한다면 당신이 묘사하고있는 것과 비슷한 상황을 만들 것입니다. 아마 걱정할 필요가 없습니다. 방아쇠 밖으로 순차적으로 많은 삽입물을 발행하는 경우 각 사이에 COMMIT을 제안합니다. 가시성을 허용합니다. – Randy

1

자식 삽입은 커밋되었거나 동일한 트랜잭션 (커밋 여부와 관계없이)에 의해 이전에 삽입 된 부모를 확인합니다.

확인할 사항 중 하나는 부모 삽입이 자동으로 기본 키 값을 유도하는지 (예 : 트리거를 통해) 여부입니다.

즉, Contracts (contract_sequence_number, ...) 값 (10437, ...)에 문을 삽입합니다.

그러나 트리거는 시퀀스에서 새로운 contract_sequence_number를 결정하고 실제로 기본 키 10438 (또는 무엇이든)을 제공합니다.

또 다른 문제는 올바른 순서로 삽입을 실행하지 않거나 단일 '트랜잭션'을 위해 풀 외부에서 다른 연결을 사용하지 않아 문제를 망칠 수있는 모든 ORM 계층 일 수 있습니다.

또한 부모의 삽입을 확인해도 오류가 반환되지 않았습니다.

SQL * Plus와 같은 일반 클라이언트를 통해 샘플 트랜잭션을 수행하고 해당 트랜잭션이 작동하는지 확인하십시오. 하위 삽입이 실패하면 계약 (예 : contract_sequence_number> 10400)에서 가장 최근의 항목을 쿼리하여 삽입 성공 여부를 확인하십시오.

+0

삽입 트리거에 대한 탁월한 생각. 제가 하나를 찾지는 못했지만 지식 전문가에게 물어볼 것입니다. – EoRaptor013

+0

또한 동일한 트랜잭션에있는 경우 자식이 부모 ID를보아야한다는 것이 나에게 의미가 있습니다. 이것이 오라클에 실제로 적용되는지 알고 있습니까? 두 개의 인서트는 분명히 동일한 트랜잭션에 있지만, 부모 레코드가 제대로 삽입되었는지는 알지만 FK 위반, 부모 발견되지는 않습니다. 이 부모/자식 문제는 일반적으로 어떻게 처리됩니까? – EoRaptor013

0

난 당신이 데이터베이스에 커밋 할 때 값을 확인합니다 이연 제약 조건을 확인하는 것이 좋습니다, 그래서 당신은 deferrable initially deferred에 FK 오류를 찾을 수 없습니다에게

1

설정하십시오 FK의 제약 조건을 피할 수있을 것입니다.

또한 단일 트랜잭션 내에서/모두 삽입을 수행해야합니다. C# 용 ODAC를 사용하는 경우 먼저 OracleTransaction을 시작하고 삽입 한 다음 commit() 및 dispose()를 수행하십시오. catch 블록에서 rollback()을 호출하고 트랜잭션에 대해 dispose()를 호출해야합니다.

PDF 버전의 Oracle Data Access Components 설명서 (11g)는 here을 참조하십시오.

희망 하시길 바랍니다

+0

감사합니다. 이것은 내가하는 일들과 거의 같습니다. C#에서는 트랜잭션을 시작하고 부모를 삽입 한 다음 첫 번째 자식을 삽입하려고합니다. 내가 제안한대로 FK 제약 조건을 변경할 수 있는지 확신 할 수 없습니다. DBA는 때로는 가장 협조적이지 않습니다. – EoRaptor013

+0

오, 그렇습니다. 나는 캐치에 롤백이 있습니다. – EoRaptor013

+0

예, DBA는 개발 노력을 지원해야합니다 (궁극적으로는 회사를 $$$로 만드는 데 도움이됩니다). 불행히도 어떤 사람들은 이렇게 생각하지 않습니다 ... – tbone

관련 문제