- NHibernate 教程
- NHibernate - 首页
- NHibernate - 概述
- NHibernate - 架构
- NHibernate - ORM
- NHibernate - 环境设置
- NHibernate - 入门
- NHibernate - 基础 ORM
- NHibernate - 基础 CRUD 操作
- NHibernate - Profiler
- 为映射文件添加 IntelliSense
- NHibernate - 数据类型映射
- NHibernate - 配置
- NHibernate - 覆盖配置
- NHibernate - 批处理大小
- NHibernate - 缓存
- NHibernate - 映射组件
- NHibernate - 关系
- NHibernate - 集合映射
- NHibernate - 级联操作
- NHibernate - 延迟加载
- NHibernate - 反向关系
- NHibernate - Load/Get
- NHibernate - LINQ
- NHibernate - 查询语言 (HQL)
- NHibernate - Criteria 查询
- NHibernate - QueryOver 查询
- NHibernate - 原生 SQL
- NHibernate - Fluent NHibernate
- NHibernate 有用资源
- NHibernate - 快速指南
- NHibernate - 有用资源
- NHibernate - 讨论
NHibernate - QueryOver 查询
本章将介绍 QueryOver 查询。这是一种新的语法,更类似于使用方法链语法的 LINQ,如下面的查询所示。
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne");
它在底层仍然是 Criteria,但是现在我们的查询是强类型的。
正如我们在 Criteria 查询中看到的,名字只是一个不透明的字符串,现在我们实际上使用的是 **x.FirstName**,因此名字的重构和重命名会在使用 QueryOver 的类似 LINQ 风格的 Criteria 查询中发生更改。
我们仍然可以做许多类似的事情,但是你不能在 QueryOver 中使用查询表达式语法,你必须使用方法链语法,并且你不能混合和匹配 LINQ 和 Criteria。
对于许多查询,QueryOver API 非常有用,并且比直接使用 Criteria 提供更容易理解的对象语法。
让我们来看一个简单的例子,我们将使用 QueryOver 获取名为 Laverne 的客户。
using System; using System.Data; using System.Linq; using System.Reflection; using HibernatingRhinos.Profiler.Appender.NHibernate; using NHibernate.Cfg; using NHibernate.Criterion; using NHibernate.Dialect; using NHibernate.Driver; using NHibernate.Linq; namespace NHibernateDemo { internal class Program { private static void Main() { var cfg = ConfigureNHibernate(); var sessionFactory = cfg.BuildSessionFactory(); using(var session = sessionFactory.OpenSession()) using(var tx = session.BeginTransaction()) { var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne"); foreach (var customer in customers.List()) { Console.WriteLine(customer); } tx.Commit(); } Console.WriteLine("Press <ENTER> to exit..."); Console.ReadLine(); } private static Configuration ConfigureNHibernate() { NHibernateProfiler.Initialize(); var cfg = new Configuration(); cfg.DataBaseIntegration(x => { x.ConnectionStringName = "default"; x.Driver<SqlClientDriver>(); x.Dialect<MsSql2008Dialect>(); x.IsolationLevel = IsolationLevel.RepeatableRead; x.Timeout = 10; x.BatchSize = 10; }); cfg.SessionFactory().GenerateStatistics(); cfg.AddAssembly(Assembly.GetExecutingAssembly()); return cfg; } } }
正如你所看到的,它在底层仍然是 Criteria,但这只是一个更好的语法。
编译并执行上述代码后,你将看到以下输出。
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be) Points: 74 HasGoldStatus: True MemberSince: 4/4/2009 12:00:00 AM (Utc) CreditRating: Neutral AverageRating: 0 Orders: Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be Press <ENTER> to exit...
其中一个缺点是,假设我们想说 **FirstName.StartsWith("A")**,如下面的程序所示。
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName.StartsWith("A")); foreach (var customer in customers.List()) { Console.WriteLine(customer); } tx.Commit();
现在让我们再次运行应用程序,你将看到这不是一个 LINQ 提供程序,因为它不知道这个 **StartsWith** 方法是什么,因此你将得到一个 **运行时异常**。
异常提示未识别的调用方法。在这里我们正在做显而易见的事情,但这并不一定有效。
让我们尝试其他方法,例如 FirstName 等于“A%”,如下面的代码所示。
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "A%"); foreach (var customer in customers.List()) { Console.WriteLine(customer); }
让我们再次运行它,你将看到我们不会得到任何结果,如下所示。
Press <ENTER> to exit...
要理解为什么我们没有得到任何结果,让我们看看 NHibernate Profiler。
正如你所看到的,FirstName 等于 A%,这不是。A% 用于 SQL 中的 like 运算符。现在我们需要在 WHERE 子句中创建一个限制,如下面的程序所示。
var customers = session.QueryOver<Customer>() .Where(Restrictions.On<Customer>(c => c.FirstName).IsLike("A%")); foreach (var customer in customers.List()) { Console.WriteLine(customer); }
让我们再次运行你的应用程序,你将看到所有名字以 A 开头的客户都被检索到。
Alejandrin Will (4ea3aef6-6bce-11e1-b0b4-6cf049ee52be) Points: 24 HasGoldStatus: False MemberSince: 10/1/2011 12:00:00 AM (Utc) CreditRating: VeryVeryGood AverageRating: 0 Orders: Order Id: 4ea3aef6-6bce-11e1-b0b5-6cf049ee52be Austyn Nolan (4ea871b6-6bce-11e1-b110-6cf049ee52be) Points: 67 HasGoldStatus: True MemberSince: 12/29/2007 12:00:00 AM (Utc) CreditRating: Neutral AverageRating: 0 Orders: Order Id: 4ea871b6-6bce-11e1-b111-6cf049ee52be Antonia Murphy (4ea871b6-6bce-11e1-b121-6cf049ee52be) Points: 72 HasGoldStatus: True MemberSince: 6/15/2009 12:00:00 AM (Utc) CreditRating: Terrible AverageRating: 0 Orders: Order Id: 4ea871b6-6bce-11e1-b122-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b123-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b124-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b125-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b126-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b127-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b128-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b129-6cf049ee52be Order Id: 4ea871b6-6bce-11e1-b12a-6cf049ee52be
它的工作方式与之前相同,只是使用了新的 **QueryOver** 语法。许多开发人员发现 LINQ 语法更容易理解,并且通常能正确处理。
如果 LINQ 无法处理它,那么你将开始查看 HQL 或 Criteria,看看是否更合适。
它只提供了一种不同的语法,因此 Criteria(create criteria 和 QueryOver)都为你提供了另一种查询机制,允许你使用 NHibernate 从数据库中提取数据。