Related information:
Http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html
The question is raised:
1. Lazy loading may cause the session to be closed, for example:
When a delay load is implemented, when orders are required, the session is queried. But at this point, because the session is closed,
So the exception is thrown:
{"initializing[model.customer#336]-failed to lazily initialize a collection of role: Model.Customer.Orders, no session or session was closed"}
The workaround is to use force immediate loading:
Method One: Add a method for the class specifically for loading orders
Public Orders loadorders (int customerId) { usingnew SessionManager (). GetSession ()) { return _session. Get<customer>(customerId). Orders; }}
Method Two: Use Nhibernateutil.initialize () for strong immediate late loading
PublicCustomer Get (intcustomerId) {Customer Customer=NULL; ISession Session=_sessionmanager.getsession (); ITransaction Transaction=session. BeginTransaction (); Try{Customer= Session. Get<customer>(CUSTOMERID); //Force Immediate Loading nhibernateutil.initialize (customer. Orders); Transaction.commit (); } Catch(Exception) {transaction. Rollback (); Throw; } finally{session. Close (); } returncustomer; } PublicCustomer Load (intcustomerId) {Customer Customer=NULL; using(_session) {customer= _session. Load<customer>(CUSTOMERID); //Force Immediate Loadingnhibernateutil.initialize (Customer. Orders); returncustomer; } }
The question is raised:
2. Lazy loading when the associated table is many, for example:
customer--"orders--" product--"company--" ...
May cause excessive loading of other entity objects, as resource consumption.
Solution:Fetch the HQL query:
"1" If the HQL query without a critical fetch is deferred to orders, as follows:
PublicIlist<customer>getbyhql () {using(_session) {//Note: If the HQL query without a critical fetch is delayed loading the orders, return_session. CreateQuery ("Select DISTINCT c from Customer C join C.orders") . List<Customer>(); }} Test code: [TestMethod] Public voidtestgetbyhql () {customerservice customerservice=NewCustomerService (); IList<Customer> customerslist =customerservice.getbyhql (); //foreach (var customer in customerslist)//{ //Console.WriteLine (Order quantity for "{0}: {1}",//customer. CustomerId, customer. Orders.count ()); //}The SQL statements from the following output, as you can see, are useless to load ordersnhibernate:Selectdistinct customer0_. CustomerId ascustomerid0_, customer0_. Version asversion0_, customer0_. Firstname asfirstname0_, customer0_. Lastname aslastname0_, customer0_. Age asage0_ fromCustomer customer0_ INNER join [Order] orders1_ on customer0_. CustomerId=orders1_. CustomerId
"2" Add fetch in HQL query to force immediate load
PublicIlist<customer>Getbyhqlandfetch () {using(_session) {//Note: If the key fetch,hql is delayed loading the orders,//is to force an immediate load by fetch . return_session. CreateQuery ("Select DISTINCT c from Customer C join fetch c.orders") . List<Customer>(); }} Test code: [TestMethod] Public voidTestgetbyhqlandfetch () {customerservice customerservice=NewCustomerService (); IList<Customer> customerslist =Customerservice.getbyhqlandfetch (); //foreach (var customer in customerslist)//{ //Console.WriteLine (Order quantity for "{0}: {1}",//customer. CustomerId, customer. Orders.count ()); //}As you can see from the SQL statement below, the HQL that added fetch has forced the orders to load immediately nhibernate:Selectdistinct customer0_. CustomerId ascustomerid0_0_, orders1_. OrderId asorderid1_1_, customer0_. Version asversion0_0_, customer0_. Firstname asfirstname0_0_, customer0_. Lastname aslastname0_0_, customer0_. Age asage0_0_, orders1_. OrderDate as orderdate1_1_, orders1_. CustomerId as customerid1_1_, orders1_. CustomerId as customerid0__, orders1_. OrderId asorderid0__ fromCustomer customer0_ INNER join [Order] orders1_ on customer0_. CustomerId=orders1_. CustomerId
The flaw of fetch, from
Http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html
Using the HQL Query method can also be loaded immediately. The HQL statement supports the following types of connections: INNER JOIN (inner join), left OUTER join (off outer join), right outer join (off-side connection), full join (fully connected, not common).
The fetch fetch connection allows an associated object to be initialized with the initialization of their parent object using only a single selection statement, which effectively replaces the outer join and deferred attribute declarations in the mapping file.
Some notes:
- Fetch is not shared with setmaxresults () or Setfirstresult () because these operations are based on the result set, and may contain duplicate data when the collection is pre-fetched, meaning that the exact number of rows cannot be known beforehand.
- Fetch cannot be used with a standalone with condition. By fetch multiple sets in a single query, you can create a Cartesian product, so please pay more attention. For many-to-many mappings, also be careful that join fetch multiple collection roles may give unexpected results in some cases.
- There is no point in using full join fetch with RIGHT join FETCH. If you use attribute-level deferred fetching, you can use the fetch all property in the first query to force NHibernate to immediately get those properties that would otherwise require lazy loading.