linq to NHibernate
什么是linq to NHibernate
什么是linq to NHibernate?说简单一点就是linq + NHibernate。
linq语句是.Net 3.5中新增的功能,从问世以来就博得了广大码农的爱好。有了linq,查询变得更方便了。
NHibernate大家也都知道的,一个ORM框架,从java的Hibernate移植过来。用于数据的持久化。
那么linq to NHibernate的目的就是像使用linq一样来查询数据库。
比如,数据库中表tb_User对应实体User。那么我们想查询用户名为”奥特曼”的用户。首先,假设有一个集合IList<User>,我们要查询出用户名为“奥特曼”的用户,linq语句大家都会写:
var user=list.Where(u=>u.Name==”奥特曼”);
语法很简洁,也很优美。如果可以想上面使用linq语句来查询数据库中的数据就好了。。于是,linq to NHibernate就产生了。linq to NHibernate是微软和开源社区优秀开发者的杰作。使得我们查询数据库更加方便了,把广大码农从select * from Table Where语句中解放出来了。当然,linq 不是万能的,但是大部分场景下使用linq to NHbernate是适用的。
linq toNhibernate和 NHibernate内置的几种查询api比较
NHibernate内置了3种查询api:原生sql查询,hql和条件查询(creteria查询)。
假设目前需要查询这样的数据:
user表中的,姓”王“的,男性,年龄在30以上的,且用户的部门是属于”IT“这个bu的员工。并且要求分页显示,每页20条数据,显示第5页。且按照注册时间降序排序。
其中用户的姓名,性别,年龄,注册时间是在user表中的。用户的部门是另一张表。部门表中有个bu字段,可能是”IT,HR“等。
既然使用了NHibernate,我们的表是和实体类做了映射的。
先来看下使用我自己写的一个简单的工具类(下面有给出)是怎么实现的吧:
NHibernateQueryHandler<User> queryHandler=new NHibernateQueryHandler<User>();
queryHandler.AddCriteria(m=>m.Name.StartWith(“王”));
queryHandler.AddCriteria(m=>m.Age>30);
queryHandler.AddCriteria(m=>m.Gender==Gender.Male);
queryHandler.AddCriteria(m=>m.Department.BU==BU.IT);
queryHandler.PageSize=20;
queryHandler.PageIndex=5;
queryHandler.OrderByDesc(m=>m.RegisterTime);
IList<User> users=queryHandler.GetList();
int Count=queryHandler.GetCount();
代码很简单,也很清晰。GetList()方法返回了第5页的20条数据,GetCount返回了中共的数量,这个数据用于前台页面显示分页控件。
大家也都用过NHibernate自带的3种查询,都没有这种类似linq的语法简单和可读性强。
自己写的一个工具类
下面是自己写的一个工具类,在上面的代码中已经使用过了。
public class NHibernateQueryHandler<T> { private readonly ISession _session = DependencyResolver.Resolve<ISessionManager>().OpenSession(); private readonly IList<Expression<Func<T, bool>>> _criterialList; private IQueryable<T> _query; private int _pageIndex = 1; private int _pageSize = int.MaxValue; public NHibernateQueryHandler() { _criterialList = new List<Expression<Func<T, bool>>>(); _query = from item in _session.Linq<T>() select item; } /// <summary> /// 添加Where条件 /// </summary> /// <param name="lambdaFunc"></param> /// <returns></returns> public NHibernateQueryHandler<T> AddCriteria(Expression<Func<T, bool>> lambdaFunc) { _criterialList.Add(lambdaFunc); return this; } /// <summary> /// 返回数据列表 /// </summary> /// <returns></returns> public IList<T> GetList() { foreach (var criterion in _criterialList) { _query = _query.Where(criterion); } _query = _query.Skip((_pageIndex - 1) * _pageSize).Take(_pageSize); return _query.ToList(); } /// <summary> /// 设置分页的页码 /// </summary> /// <param name="index"></param> /// <returns></returns> public NHibernateQueryHandler<T> SetPageIndex(int index) { _pageIndex = index; return this; } /// <summary> /// 设置分页的页面大小 /// </summary> /// <param name="size"></param> /// <returns></returns> public NHibernateQueryHandler<T> SetPageSize(int size) { _pageSize = size; return this; } /// <summary> /// 计算返回的数据数量 /// </summary> /// <returns></returns> public int GetCount() { foreach (var criterion in _criterialList) { _query = _query.Where(criterion); } return _query.Count(); } /// <summary> /// 升序(ASC)排序 /// </summary> /// <param name="keySlec"></param> /// <returns></returns> public NHibernateQueryHandler<T> OrderBy(Expression<Func<T, object>> keySlec) { _query = _query.OrderBy(keySlec); return this; } /// <summary> /// 降序(DESC)排序 /// </summary> /// <param name="keySlec"></param> /// <returns></returns> public NHibernateQueryHandler<T> OrderByDesc(Expression<Func<T, object>> keySlec) { _query = _query.OrderByDescending(keySlec); return this; } }
相关API
处理可空类型
如果一个时间的类型是可空的:DateTime?,那么在查询的时候需要注意下。
直接使用query.Select(date=>date==new DataTime(2013,11,11)).而不要使用query.Select(date=>date.Value==new DataTime(2013,11,11))
[Test] public void Test001() { NHibernateQueryHandler<Vacation> queryHandler = new NHibernateQueryHandler<Vacation>(); queryHandler.AddCriteria(m => m.EndTime != null); //you will get an error: could not resolve property: EndTime.Value of: HelloWorld.Model.Vacation //queryHandler.AddCriteria(m => m.EndTime.Value == DateTime.Now.Date); queryHandler.AddCriteria(m => m.EndTime == DateTime.Now.Date); var list= queryHandler.GetList(); Console.WriteLine(list.Count); Console.WriteLine(list[0].ID); }
关于NHibernate的查询api,可以参见NHibernate.Linq的官方源码中的单元测试部分:
注意事项
NHibernate2中没有实现linq查询的功能,但是NHibernate 3中本身就有linq查询的功能,不在需要第三方库来实现linq功能。
注:该NHIbernate.Linq.dll 依赖的NHibernate版本是2.1.2.4000.如果使用的NHibernate版本是2.1.2.4000,可直接使用。如果使用的NHibernate版本比2.1.2.4000低,想使用该dll,需添加以下配置到web.config或app.config中。
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" /> <bindingRedirect oldVersion="2.1.0.3001" newVersion="2.1.2.4000" /> </dependentAssembly> </assemblyBinding> </runtime>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?