01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即載入

來源:互聯網
上載者:User

標籤:style   c   class   blog   code   java   

相關資料:

http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html

 

 

問題的提出:

1.消極式載入,可能會引起session已經關閉的異常,例如:

當實現消極式載入,當需要Orders時,會通過session去查詢,session。但此時,由於session已經關閉,

所以會拋出異常:

{"Initializing[Model.Customer#336]-failed to lazily initialize a collection of role: Model.Customer.Orders, no session or session was closed"}

 

解決方案是,使用強制立即載入:

 

方法一:為類添加一個方法專門用於載入Orders

public Orders LoadOrders(int customerId){    using (ISession _session = new SessionManager().GetSession())    {        return _session.Get<Customer>(customerId).Orders;    }}

 

方法二:用NHibernateUtil.Initialize()進行強立即遲載入

        public Customer Get(int customerId)        {            Customer customer = null;            ISession session = _sessionManager.GetSession();            ITransaction transaction = session.BeginTransaction();            try            {                customer = session.Get<Customer>(customerId);                //強制立即載入                NHibernateUtil.Initialize(customer.Orders);                transaction.Commit();            }            catch (Exception)            {                transaction.Rollback();                throw;            }            finally            {                session.Close();            }            return customer;        }        public Customer Load(int customerId)        {            Customer customer = null;            using (_session)            {                 customer = _session.Load<Customer>(customerId);                //強制立即載入                NHibernateUtil.Initialize(customer.Orders);                  return customer;            }        }

 

問題的提出:

2.消極式載入,當關聯的表很多,例如:

 Customer--》Orders--》Product--》Company--》。。。

可能會引起連帶載入過多其他實體物件,照成資源消耗。

 

解決方案:fetch的HQL查詢:

   【1】如果沒有用關鍵fetch的HQL查詢是對Orders進行消極式載入的,如下所示:

 

        public IList<Customer> GetByHQL()        {            using (_session)            {                //注意;如果沒有用關鍵fetch的HQL查詢是對Orders進行消極式載入的,                return _session.CreateQuery("select DISTINCT  c from Customer c  join  c.Orders ")                               .List<Customer>();            }        }測試代碼:       [TestMethod]        public void TestGetByHQL()        {            CustomerService customerService = new CustomerService();            IList<Customer> customersList = customerService.GetByHQL();            //foreach (var customer in customersList)            //{            //    Console.WriteLine("{0}的Order數量:{1}",             //        customer.CustomerId, customer.Orders.Count());            //}        }從下面輸出的SQL語句,可以看出,沒用載入OrdersNHibernate:     select        distinct customer0_.CustomerId as CustomerId0_,        customer0_.Version as Version0_,        customer0_.Firstname as Firstname0_,        customer0_.Lastname as Lastname0_,        customer0_.Age as Age0_     from        Customer customer0_     inner join        [    Order] orders1_         on customer0_.CustomerId=orders1_.CustomerId

 

 

   【2】在HQL查詢中加入fetch進行強制立即載入

        public IList<Customer> GetByHQLAndFetch()        {            using (_session)            {                //注意;如果沒喲關鍵fetch,HQL是對Orders進行消極式載入的,                //就是通過fetch進行強制立即載入                return _session.CreateQuery("select DISTINCT  c from Customer c join fetch c.Orders ")                               .List<Customer>();            }        }測試代碼:        [TestMethod]        public void TestGetByHQLAndFetch()        {            CustomerService customerService = new CustomerService();            IList<Customer> customersList = customerService.GetByHQLAndFetch();            //foreach (var customer in customersList)            //{            //    Console.WriteLine("{0}的Order數量:{1}",             //        customer.CustomerId, customer.Orders.Count());            //}        }從下面輸出的SQL語句,可以看出,添加了fetch的HQL對Orders進行了強制立即載入NHibernate:     select        distinct customer0_.CustomerId as CustomerId0_0_,        orders1_.OrderId as OrderId1_1_,        customer0_.Version as Version0_0_,        customer0_.Firstname as Firstname0_0_,        customer0_.Lastname as Lastname0_0_,        customer0_.Age as Age0_0_,        orders1_.OrderDate as OrderDate1_1_,        orders1_.CustomerId as CustomerId1_1_,        orders1_.CustomerId as CustomerId0__,        orders1_.OrderId as OrderId0__     from        Customer customer0_     inner join        [    Order] orders1_         on customer0_.CustomerId=orders1_.CustomerId

 

fetch的缺陷,來自

http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html

 

使用HQL查詢方法也可以立即載入。HQL語句支援的連線類型為:inner join(內串連)、left outer join(左外串連)、right outer join(右外串連)、full join(全串連,不常用)。

“抓取fetch”串連允許僅僅使用一個選擇語句就將相關聯的對象隨著他們的父物件的初始化而被初始化,可以有效代替了對應檔中的外聯結與延遲屬性聲明。

幾點注意:

  • fetch不與setMaxResults() 或setFirstResult()共用,因為這些操作是基於結果集的,而在預先抓取集合時可能包含重複的資料,也就是說無法預Crowdsourced Security Testing道精確的行數。
  • fetch還不能與獨立的with條件一起使用。通過在一次查詢中fetch多個集合,可以製造出笛卡爾積,因此請多加註意。對多對多映射來說,同時join fetch多個集合角色可能在某些情況下給出並非預期的結果,也請小心。
  • 使用full join fetch 與 right join fetch是沒有意義的。 如果你使用屬性層級的延遲擷取,在第一個查詢中可以使用 fetch all properties 來強制NHibernate立即取得那些原本需要消極式載入的屬性。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.