2011-04-01 4 views
2

나는 Customer와 Account라는 두 개의 엔티티를 가지고있다. 고객은 많은 계정을 가지고 있습니다.NHibernate - 로딩 콜렉션에 대한 불법적 접근

고객에 대한 나의 매핑은 다음과 같습니다

<bag cascade="all" name="Accounts" table ="Accounts" mutable="true" inverse="true"> 
    <key> 
    <column name="Customer_Id" /> 
    </key> 
    <one-to-many class="Account, POCOEntities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
</bag> 

계정에 대한 나의 매핑은 다음과 같습니다

var customer = _customerRepository.GetById(custID); 

:

내 응용 프로그램에서
<many-to-one cascade="all" class="Customer, POCOEntities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Customer"> 
    <column name="Customer_Id" /> 
</many-to-one> 

, 내가 그들의 ID를 기반으로 고객을 검색 그런 다음 고객에게 첫 번째 계정을 가져 오려고 시도합니다.

"NHibernate.LazyInitializationException :로드 컬렉션에 대한 불법적 인 접근"

나는이 문제를 여기에 게시하지만 아무것도 작동하지 않습니다에 대한 다른 솔루션을 시도했습니다 (3210)

Account account = customer.Accounts.FirstOrDefault(); 

나는 다음 예외가 발생합니다.

var acc = from a in _accountRepository.GetAll() 
        where a.Customer.Equals(customer) 
        select a; 

모든 나는 위의 코드에서 수행 한 내가조차 사용하지 않는 변수를 만들 수 있습니다 : 무슨 정말 이상한 것은 내가 계정에 액세스하려고 직전에 내가 다음 코드를 삽입하면 다음 모든 작품입니다. 어떻게 든 그것은 "Account account = customer.Accounts.FirstOrDefault();"문을 발생시킵니다. 성공하기.

누구에게 무슨 일이 일어나고 있는지 아이디어가 있습니까?

+0

"변경 가능"속성을 제거하려고 시도 했습니까? – mathieu

답변

4

저는 이것이 매우 간단하다고 생각합니다. 더 이상 열린 엔터티가 해당 엔터티에 연결되어 있지 않습니다. 그리고 이것은 세션 관리 (열기/닫기 세션)를 저장소에 대한 책임으로 남겨두기 때문에 이것이라고 생각합니다. 잘못된 것입니다.

+0

세션 열기 및 닫기는 별도의 작업 단위 (UOW) 클래스에 의해 처리됩니다. 동일한 작업 단위 (UOW)가 모든 저장소에 전달되어 동일한 작업 단위 (UOW)와 연관됩니다.나는이 책임을 저장소 자체에 맡기지 않는다. – JMc

0

문제는 이전에 제안 된 개별 저장소에 의해 처리 되었기 때문에 'ISession'이 닫혔다는 사실이었습니다.

문제의 원인은 내 비즈니스 메서드 인 PlaceOrder()의 범위를 벗어난 내 UnitOfWork (ISession)을 선언했기 때문입니다. 예를 들어 :

ISession myUnitOfWork = new ISession(); 


public void PlaceOrder() 
{ 

    var myRepository = new IRepository<Customer>(myUnitOfWork); 
    .... 
    .... 
    Commit(); 
} 

는 그래서 PlaceOrder() 메소드의 최초의 호출은 괜찮다고하지만, 추가 통화에서 ISession는 메시지 따라서 "로드 컬렉션에 불법적 인 접근"을 폐쇄했다. 이 솔루션은 PlaceOrder() 메소드 내에서 ISession를 선언했다 :
public void PlaceOrder() 
{ 
    ISession myUnitOfWork = new ISession(); 
    var myRepository = new IRepository<Customer>(myUnitOfWork); 
    ....     

는 궁극적으로이 문제는 작업 단위의 개념에 대한 이해의 부족의 결과였다. 내 이해가 정확하다면, 위의 PlaceOrder와 같은 각 비즈니스 메소드는 새로운 트랜잭션이므로 시작시 열리고 마지막에 닫히는 Session이 필요합니다. 메서드의 범위를 벗어난 ISession을 단 한번 선언해야한다고 생각했습니다.

+0

답변은 2 년 전에 작성되었으므로 이번에는이 개념을 잘 이해할 수 있지만 ISession은 일반적으로 Ninject 또는 Castle Windsor와 같은 IoC 컨테이너를 통해 저장소 클래스의 생성자에 주입되어 UoW의 이점을 활용합니다. IRepository는 비즈니스 클래스의 생성자에도 삽입되므로 처음에는 Session을 열지 말고 끝내야합니다. – Andy

0

나는 또한이 오류가 발생했다. 그러나 나는 단지 중단 점에서만 그것을 알아 차렸다. DebuggerDisplay 특성을 지연 설치 한 속성을 표시하려고하면 오류가 발생했습니다.

관련 문제