我有两个实体,即客户和帐户。客户有很多帐户。
我对客户的映射是:
<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>
我对帐户的映射是:
<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检索客户:
var customer = _customerRepository.GetById(custID);
然后,我试着通过以下方式获得客户的第一个帐户:
Account account = customer.Accounts.FirstOrDefault();
然后我收到以下异常:“NHibernate.LazyInitializationException:非法访问加载集合”
我已尝试过此处发布此问题的其他解决方案,但没有任何效果。真的很奇怪的是,如果我在尝试访问帐户之前插入以下代码,那么一切正常:
var acc = from a in _accountRepository.GetAll()
where a.Customer.Equals(customer)
select a;
我在前面的代码中所做的全部是创建一个我甚至不使用的变量。它以某种方式导致语句“Account account = customer.Accounts.FirstOrDefault();”虽然成功了。
任何人都有任何想法在这里发生了什么?
答案 0 :(得分:4)
我认为这很简单:您不再拥有与该实体关联的开放ISession。并且,我认为这是因为将会话管理(打开/关闭会话)作为对存储库的责任,这是错误的。
答案 1 :(得分:0)
这里的问题实际上是'ISession'被关闭了,虽然这并不是因为它被如前所述的个别存储库处理。
问题的原因是我将我的UnitOfWork(ISession)声明在我的业务方法范围之外 - PlaceOrder()。例如:
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)都是一个新事务,因此需要在开始时打开ISession并在结束时关闭。我在方法范围之外宣称ISession认为它只需要声明一次。
答案 2 :(得分:0)
我也遇到了这个错误 - 但我只是在断点时发现了它。我的错误是由DebuggerDisplay属性试图显示懒惰加载的属性引起的。