开发者

NHibernate - illegal access to loading collection

开发者 https://www.devze.com 2023-02-21 01:58 出处:网络
I have two entities, Customer and Account. A Customer has many accounts. My mapping for Customer is :

I have two entities, Customer and Account. A Customer has many accounts.

My mapping for Customer is :

<bag cascade="all" name="Accounts" table ="Accounts" mutable="true" inverse="true">
  <key>
    <column name="Customer_Id" />
  </key>
  <one-to-many class="Account, P开发者_开发技巧OCOEntities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

My mapping for Account is:

<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>

In my application, I retrieve a customer based on their ID:

var customer = _customerRepository.GetById(custID);

I then try to get the customers first account with:

Account account = customer.Accounts.FirstOrDefault();

I then receive the following exception: "NHibernate.LazyInitializationException: illegal access to loading collection"

I've tried other solutions for this problem posted here but nothing is working. Whats really odd is if I insert the following code just before I try to access the account then everything works:

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

All I've done in the preceding code is create a variable that I don't even use. Somehow it causes the statement "Account account = customer.Accounts.FirstOrDefault();" to succeed though.

Anyone have any ideas what's going on here?


I think it's quite simple: you no longer have an open ISession associated to the entity. And, I think that this is due because leave your session-management (open / close session) as a responsability to the Repository, and that's wrong.


The problem here was in fact that the 'ISession' was closed, although this was not because of it being handled by individual repositories as previously suggested.

The cause of the issue was that I declared my UnitOfWork (ISession) outside of the scope of my business method - PlaceOrder(). For example:

ISession myUnitOfWork = new ISession();


public void PlaceOrder()
{

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

So the first call to the PlaceOrder() method was fine, but on additional calls the ISession had been closed, hence the "Illegal Access to loading collection" message. The solution was to declare the ISession within the PlaceOrder() method:

public void PlaceOrder()
{
    ISession myUnitOfWork = new ISession();
    var myRepository = new IRepository<Customer>(myUnitOfWork);
    ....                

Ultimately this issue was the result of a lack of understanding of the the concept of a Unit of Work. If my understanding is now correct, then each business method (such as PlaceOrder above) is a new transaction and therefore requires an ISession to be opened at the start and closed at the end. I was declaring the ISession outside the scope of the method thinking that it only needed to be declared once.


I was also getting this error - but I only noticed it at a break point. My error was caused by having the DebuggerDisplay attribute trying to show properties that were being loaded lazily.

0

精彩评论

暂无评论...
验证码 换一张
取 消