문제

두 가지 관련 객체가 있습니다 : 프로그램 세션과 프로그램 타스크, 일대일 관계가 있습니다. 프로그램에는 많은 프로그램이 있습니다. 따라서 물체는 다음과 같습니다.

public class ProgramSession
{
    public virtual IList<ProgramTask> ProgramTasks
    {
        get { return _programTasks; }
        set { _programTasks = value; }
    }
}

public class ProgramTask
{
    public virtual ProgramSession ProgramSession
    {
        get { return _programSession; }
        set { _programSession = value; }
    }
}

그리고 매핑 ...

programession.hbm.xml

<bag name="ProgramTasks" lazy="false" cascade="all-delete-orphan" inverse="true" >
    <key column="SessionUid"></key>
    <one-to-many class="ProgramTask"></one-to-many>
</bag>

programtask.hbm.xml

<many-to-one name="ProgramSession" column="SessionUid" class="ProgramSession" />

프로그램 작업의 프로그램 세션을 변경하려고 할 때 문제가 시작됩니다.

프로그램에서 Programtasks를 제거하면 기존 세션의 ProgramTasks 목록 속성을 새 세션에서 동일한 속성에 추가하면 NHibernate는 삭제 된 객체가 재설정 될 것이라고 알려줍니다.

단순히 programtask.programsession 객체의 값을 변경하면 저장에 문제가 없습니다. 그러나 nhibernate 세션이 새로 고침 될 때까지 programtasks 속성 (두 세션 모두)이 동기화되지 않기 때문에 즉시 저장하지 않으면 이상한 행동을 취합니다.

목록을 직접 수정하지 않고 Programtask.programsession 객체 변경하면 유효하지 않은 상태가 생깁니다. 예를 들어 다음 코드를 선택하십시오.

programTask.ProgramSession = newProgramSession;
Assert.That(newProgramSession.ProgramTasks.Contains(programTask)); // fails
Assert.That(!oldProgramSession.ProgramTasks.Contains(programTask)); // fails

이는 나중에 실행 된 코드에서 더 문제가되며, 프로그램 컬렉션이 ProgramSession 속성과 동기화되어 있다고 가정합니다. 예를 들어:

foreach(var programTask in programSession.ProgramTasks)
{
    // whatever
}

내가 이것을 해결하는 데 사용했던 한 가지 해킹은 목록을 쿼리하는 것이 었습니다. 나는 어디서나 그것을 사용할 수 없으며 분명히 나쁜 해결책이지만 문제를 강조합니다.

var tasksActuallyInSession =
    programSession.ProgramTasks
        .Where(task => task.ProgramSession == programSession)
        .ToList();

이런 종류의 상황을 처리 할 수있는 방법이 있습니까? 모범 사례? 내가 뭔가 잘못하고 있습니까? 매핑이 잘못 되었습니까? 설정해야 할 초록 비밀 NHibernate 플래그가 있습니까?

도움이 되었습니까?

해결책

당신이 여기서하는 일을 모든 것을 이해하는지 확실하지 않습니다. 몇 가지 생각 :

당신이 움직이기로 결정했다면 ProgramTasks 주위에, 그들은 독립적이며 사용하지 않아야합니다. cascade="all-delete-orphan". 이렇게하면 NH는 제거합니다 ProgramTask 데이터베이스에서 a에서 제거 할 때 ProgramSession.

사용하여 매핑하십시오 cascade="none" 그리고 물체의 수명주기를 직접 제어하십시오. (이것은 의미 : a ProgramSession 저장됩니다. 더 이상 사용되지 않을 때 삭제하십시오.)

이것이 문제인지 확실하지 않지만, 역 참조가 있으면 코드가 참조를 일관성있게 만들 수 있습니다. 물론, 데이터베이스에 저장하고 빈 세션에로드 한 후 참고 문헌이 정리됩니다. 데이터베이스에는 외국 키가 하나만 있기 때문입니다. 그러나 이것이해야 할 방식이 아닙니다. 참조를 관리하는 것은 NH의 책임이 아닙니다. (유일한 책임은 메모리에서하고있는 일을 지속하는 것입니다.) 따라서 메모리에서 일관성을 유지하고 비즈니스 논리가 뒤에없는 것처럼 비즈니스 논리를 구현해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top