[NHibernate]一對多關系(關聯查詢)


目錄

寫在前面

文檔與系列文章

一對多查詢

總結

寫在前面

上篇文章介紹了nhibernate的一對多關系如何配置,以及級聯刪除,級聯添加數據的內容。這篇文章我們將學習nhibernate中的一對多關系的關聯查詢。前面文章中也介紹的nhibernate的查詢:HQL,條件查詢,原生SQL查詢。

文檔與系列文章

[Nhibernate]體系結構

[NHibernate]ISessionFactory配置

[NHibernate]持久化類(Persistent Classes)

[NHibernate]O/R Mapping基礎

[NHibernate]集合類(Collections)映射 

[NHibernate]關聯映射

[NHibernate]Parent/Child

[NHibernate]緩存(NHibernate.Caches)

[NHibernate]NHibernate.Tool.hbm2net

[NHibernate]Nullables

[NHibernate]Nhibernate如何映射sqlserver中image字段

[NHibernate]基本配置與測試 

[NHibernate]HQL查詢 

[NHibernate]條件查詢Criteria Query

[NHibernate]增刪改操作

[NHibernate]事務

[NHibernate]並發控制

[NHibernate]組件之依賴對象

[NHibernate]一對多關系(級聯刪除,級聯添加)

一對多查詢

原生sql關聯查詢

查詢某一個客戶的信息,以及該客戶所下的訂單信息

 1         /// <summary>
 2         /// 查詢某客戶信息與該客戶的訂單信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public IList<Customer> GetCustomerOrders(Guid customerID)
 7         {
 8             //獲得ISession實例
 9             ISession session = NHibernateHelper.GetSession();
10             //實例化IQuery接口;使用ISession.CreateSQLQuery()方法,傳遞的參數是SQL查詢語句
11             return session.CreateSQLQuery("select distinct tb_customer.*,tb_order.* from tb_customer "
12                 + "inner join tb_order on tb_customer.customerid=tb_order.customerid where tb_customer.customerid=:id")
13                 .AddEntity("Customer", typeof(Customer))
14                 .SetGuid("id", customerID)
15                 .List<Customer>();
16         }

注意,此時使用的是真正的sql,里面使用的是數據表,這點與hql不同(hql中使用的是面向對象的概念,使用的是數據表映射的實體類對象)。

 1         /// <summary>
 2         /// 按客戶id查詢客戶信息及訂單信息
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         protected void btnSearchByID_Click(object sender, EventArgs e)
 7         {
 8             Business.CustomerBusiness customerBusiness = new Business.CustomerBusiness();
 9             this.rptCustomerList.DataSource = customerBusiness.GetCustomerOrders(new Guid("B0720295-9541-40B3-9994-610066224DB8"));
10             this.rptCustomerList.DataBind();
11         }

 生成的sql語句,因為使用的inner join ,測試的數據為一個客戶對應的訂單有2個,所以查詢出來的數據有2條。

HQL關聯查詢

使用HQL查詢,某一個客戶的信息,以及該客戶所下的訂單信息

 1         /// <summary>
 2         /// HQL查詢某客戶信息與該客戶的訂單信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public IList<Customer> GetCustomerOrdersByHQL(Guid customerID)
 7         {
 8             //獲得ISession實例
 9             ISession session = NHibernateHelper.GetSession();
10             return session.CreateQuery("select c from Customer c inner join c.Orders  where c.CustomerID=:id")
11                 .SetGuid("id", customerID)
12                 .List<Customer>();
13         }

通過觀察,可以發現inner join 后面的Orders為實體Customer的一個屬性,這種面向對象的方式更符合咱們的開發習慣。

生成的sql語句為

Criteria API條件查詢

使用Criteria API條件查詢,某一個客戶的信息,以及該客戶所下的訂單信息

使用CreateCriteria()在關聯之間導航,很容易地在實體之間指定約束。這里第二個CreateCriteria()返回一個ICriteria的新實例,並指向Orders實體的元素。在查詢中子對象使用子CreateCriteria語句,這是因為實體之間的關聯我們在映射文件中已經定義好了。

還有一種方法使用CreateAlias()不會創建ICriteria的新實例。

 1         /// <summary>
 2         /// Criteria API查詢某客戶信息與該客戶的訂單信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public IList<Customer> GetCustomerOrdersByCriteria(Guid customerID)
 7         {
 8             //獲得ISession實例
 9             ISession session = NHibernateHelper.GetSession();
10             return session.CreateCriteria(typeof(Customer))
11                 .CreateCriteria("Orders")
12                 .Add(Restrictions.Eq("Customer.CustomerID", customerID))
13                 .List<Customer>();
14         }

這個地方需要注意因為在Order和Customer實體中都有CustomerID屬性,需要指明是哪個CustomerID。
生成的sql

這種方式得到的結果可能重復,可通過如下方式進行預過濾

預過濾

使用ICriteria接口的SetResultTransformer(IResultTransformer resultTransformer)方法返回滿足特定條件的Customer。上面例子中使用條件查詢,觀察其生成的SQL語句並沒有distinct,這時可以使用NHibernate.Transform命名空間中的方法或者使用NHibernate提供的NHibernate.CriteriaUtil.RootEntity、NHibernate.CriteriaUtil.DistinctRootEntity、NHibernate.CriteriaUtil.AliasToEntityMap靜態方法實現預過濾的作用。那么上面的查詢應該修改為:

 1         /// <summary>
 2         /// Criteria API查詢某客戶信息與該客戶的訂單信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public IList<Customer> GetCustomerOrdersByCriteria(Guid customerID)
 7         {
 8             //獲得ISession實例
 9             ISession session = NHibernateHelper.GetSession();
10             return session.CreateCriteria(typeof(Customer))
11                 .CreateCriteria("Orders")
12                 .Add(Restrictions.Eq("Customer.CustomerID", customerID))
13                 //預過濾重復的結果
14                 .SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())
15                 //或者.SetResultTransformer(NHibernate.CriteriaUtil.DistinctRootEntity)
16                 .List<Customer>();
17         }

生成的sql語句

沒預過濾的

使用預過濾的

此時查詢的Order為一條。通過對比你會發現他們生成的sql語句一樣,真正實現過濾的應該是在內存中做的。

投影

調用SetProjection()方法可以實現應用投影到一個查詢中。NHibernate.Criterion.Projections是Projection的實例工廠,Projections提供了非常多的方法。

 1         /// <summary>
 2         /// 投影查詢某客戶信息與該客戶的訂單信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public IList<Customer> GetCustomerOrdersByProjection(Guid customerID)
 7         {
 8             //獲得ISession實例
 9             ISession session = NHibernateHelper.GetSession();
10             IList<Guid> ids = session.CreateCriteria(typeof(Customer))
11                 .SetProjection(Projections.Distinct(
12                 Projections.ProjectionList()
13                 .Add(Projections.Property("CustomerID"))
14                 )
15                 )
16                 .CreateCriteria("Orders")
17         .Add(Restrictions.Eq("Customer.CustomerID", customerID))
18         .List<Guid>();
19             return session.CreateCriteria(typeof(Customer))
20        .Add(Restrictions.In("CustomerID", ids.ToArray<Guid>()))
21        .List<Customer>();
22         }

 

我們可以添加若干的投影到投影列表中,例如這個例子我添加一個CustomerId屬性值到投影列表中,這個列表中的所有屬性值都設置了Distinct投影,第一句返回訂單的客戶CustomerId,第二句根據返回的CustomerId查詢顧客列表。達到上面的目的。這時發現其生成的SQL語句中有distinct。我們使用投影可以很容易的組合我們需要的各種方法。

生成的sql語句

總結

這里介紹了處理一對多關系的關聯查詢的方式,希望對你有所幫助。

參考地址:http://www.cnblogs.com/lyj/archive/2008/10/26/1319889.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM