[NHibernate]一对多关系(关联查询)
2014-11-04 08:22
281 查看
目录
写在前面文档与系列文章
一对多查询
总结
写在前面
上篇文章介绍了nhibernate的一对多关系如何配置,以及级联删除,级联添加数据的内容。这篇文章我们将学习nhibernate中的一对多关系的关联查询。前面文章中也介绍的nhibernate的查询:HQL,条件查询,原生SQL查询。文档与系列文章
[Nhibernate]体系结构[NHibernate]ISessionFactory配置
[NHibernate]持久化类(Persistent Classes)
[NHibernate]O/R Mapping基础
[NHibernate]集合类(Collections)映射%26nbsp;
[NHibernate]关联映射
[NHibernate]Parent/Child
[NHibernate]缓存(NHibernate.Caches)
[NHibernate]NHibernate.Tool.hbm2net
[NHibernate]Nullables
[NHibernate]Nhibernate如何映射sqlserver中image字段
[NHibernate]基本配置与测试%26nbsp;
[NHibernate]HQL查询%26nbsp;
[NHibernate]条件查询Criteria Query
[NHibernate]增删改操作
[NHibernate]事务
[NHibernate]并发控制
[NHibernate]组件之依赖对象
[NHibernate]一对多关系(级联删除,级联添加)
一对多查询
原生sql关联查询
查询某一个客户的信息,以及该客户所下的订单信息1 /// %26lt;summary%26gt; 2 /// 查询某客户信息与该客户的订单信息 3 /// %26lt;/summary%26gt; 4 /// %26lt;param name="customerID"%26gt;%26lt;/param%26gt; 5 /// %26lt;returns%26gt;%26lt;/returns%26gt; 6 public IList%26lt;Customer%26gt; 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%26lt;Customer%26gt;(); 16 }
注意,此时使用的是真正的sql,里面使用的是数据表,这点与hql不同(hql中使用的是面向对象的概念,使用的是数据表映射的实体类对象)。
1 /// %26lt;summary%26gt; 2 /// 按客户id查询客户信息及订单信息 3 /// %26lt;/summary%26gt; 4 /// %26lt;param name="sender"%26gt;%26lt;/param%26gt; 5 /// %26lt;param name="e"%26gt;%26lt;/param%26gt; 6 protected void btnSearchByID_Click(object sender, EventArgs e) 7 { 8 Business.CustomerBusiness customerBusiness = new Business.CustomerBusiness(); 9 this.rptCustomerList.DataS 4000 ource = customerBusiness.GetCustomerOrders(new Guid("B0720295-9541-40B3-9994-610066224DB8")); 10 this.rptCustomerList.DataBind(); 11 }
%26nbsp;生成的sql语句,因为使用的inner join ,测试的数据为一个客户对应的订单有2个,所以查询出来的数据有2条。
HQL关联查询
使用HQL查询,某一个客户的信息,以及该客户所下的订单信息1 /// %26lt;summary%26gt; 2 /// HQL查询某客户信息与该客户的订单信息 3 /// %26lt;/summary%26gt; 4 /// %26lt;param name="customerID"%26gt;%26lt;/param%26gt; 5 /// %26lt;returns%26gt;%26lt;/returns%26gt; 6 public IList%26lt;Customer%26gt; 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%26lt;Customer%26gt;(); 13 }
通过观察,可以发现inner join 后面的Orders为实体Customer的一个属性,这种面向对象的方式更符合咱们的开发习惯。
生成的sql语句为
Criteria API条件查询
使用Criteria API条件查询,某一个客户的信息,以及该客户所下的订单信息使用CreateCriteria()在关联之间导航,很容易地在实体之间指定约束。这里第二个CreateCriteria()返回一个ICriteria的新实例,并指向Orders实体的元素。在查询中子对象使用子CreateCriteria语句,这是因为实体之间的关联我们在映射文件中已经定义好了。
还有一种方法使用CreateAlias()不会创建ICriteria的新实例。
1 /// %26lt;summary%26gt; 2 /// Criteria API查询某客户信息与该客户的订单信息 3 /// %26lt;/summary%26gt; 4 /// %26lt;param name="customerID"%26gt;%26lt;/param%26gt; 5 /// %26lt;returns%26gt;%26lt;/returns%26gt; 6 public IList%26lt;Customer%26gt; 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%26lt;Customer%26gt;(); 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 /// %26lt;summary%26gt; 2 /// Criteria API查询某客户信息与该客户的订单信息 3 /// %26lt;/summary%26gt; 4 /// %26lt;param name="customerID"%26gt;%26lt;/param%26gt; 5 /// %26lt;returns%26gt;%26lt;/returns%26gt; 6 public IList%26lt;Customer%26gt; 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%26lt;Customer%26gt;(); 17 }
生成的sql语句
没预过滤的
使用预过滤的
此时查询的Order为一条。通过对比你会发现他们生成的sql语句一样,真正实现过滤的应该是在内存中做的。
投影
调用SetProjection()方法可以实现应用投影到一个查询中。NHibernate.Criterion.Projections是Projection的实例工厂,Projections提供了非常多的方法。
1 /// %26lt;summary%26gt; 2 /// 投影查询某客户信息与该客户的订单信息 3 /// %26lt;/summary%26gt; 4 /// %26lt;param name="customerID"%26gt;%26lt;/param%26gt; 5 /// %26lt;returns%26gt;%26lt;/returns%26gt; 6 public IList%26lt;Customer%26gt; GetCustomerOrdersByProjection(Guid customerID) 7 { 8 //获得ISession实例 9 ISession session = NHibernateHelper.GetSession(); 10 IList%26lt;Guid%26gt; 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%26lt;Guid%26gt;(); 19 return session.CreateCriteria(typeof(Customer)) 20 .Add(Restrictions.In("CustomerID", ids.ToArray%26lt;Guid%26gt;())) 21 .List%26lt;Customer%26gt;(); 22 }
%26nbsp;
我们可以添加若干的投影到投影列表中,例如这个例子我添加一个CustomerId属性值到投影列表中,这个列表中的所有属性值都设置了Distinct投影,第一句返回订单的客户CustomerId,第二句根据返回的CustomerId查询顾客列表。达到上面的目的。这时发现其生成的SQL语句中有distinct。我们使用投影可以很容易的组合我们需要的各种方法。
生成的sql语句
总结
这里介绍了处理一对多关系的关联查询的方式,希望对你有所帮助。参考地址:http://www.cnblogs.com/lyj/archive/2008/10/26/1319889.html
相关文章推荐
- [NHibernate]一对多关系(关联查询)
- [NHibernate]一对多关系(关联查询)
- NHibernate之旅(9):探索父子关系(一对多关系)
- NHibernate之旅(11):探索多对多关系及其关联查询
- NHibernate之旅(10):探索父子(一对多)关联查询
- 【转】[NHibernate]一对多关系(级联删除,级联添加)
- NHibernate初探(四) 一对多关系测试示例
- Nhibernate回顾---父子关系查询 关联查询 使用HQL和Criteria API
- [NHibernate]多对多关系(关联查询)
- NHibernate初探 一对多关系测试
- [转]NHibernate之旅(9):探索父子关系(一对多关系)
- NHibernate之旅(9):探索父子关系(一对多关系)
- [转]NHibernate之旅(10):探索父子(一对多)关联查询
- [NHibernate]一对多关系(级联删除,级联添加)
- Asp.Net大型项目实践(4)-用NHibernate保存和查询我们的业务领域对象之多表关联查询(附源码)
- [转]NHibernate之旅(11):探索多对多关系及其关联查询
- NHibernate之旅(9):探索父子关系(一对多关系)
- NHibernate之旅(9):探索父子关系(一对多关系)
- Asp.Net大型项目实践(4)-用NHibernate保存和查询我们的业务领域对象之多表关联查询(附源码)
- NHibernate之旅(11):探索多对多关系及其关联查询