深入理解NHibernate的查询API

NHibernate是一个流行的.NET框架下的ORM(对象关系映射)工具,它通过将数据库中的表映射到.NET对象,使得开发者能够以面向对象的方式来处理数据库操作。NHibernate的设计遵循了关注点分离原则,确保了工作单元(Unit Of Work)和其配置(实体和映射)之间的分离。虽然手动编写映射类可能会让一些开发者感到复杂,但NHibernate和Entity Framework一样,都支持POCO(Plain Old CLR Object)实体的创建。对于ORM来说,最重要的就是从数据库中检索数据的方式,以及在处理大量数据时优化响应时间。本文将介绍NHibernate中的两种查询API:Criteria API和QueryOver API。

为了理解这两种查询API的区别,需要有一定的FluentNHibernate经验。Fluent NHibernate是一个NHibernate的映射框架,它使用流畅的接口来定义映射,使得映射过程更加直观和灵活。

Criteria API

作为ORM,NHibernate操作的是对象而不是表。使用Criteria API进行查询是简单、直观且可扩展的。要使用Criteria查询API,首先需要创建一个NHibernate.ICriteria的新实例,它与一个持久化实体关联,并代表对其的查询。例如,对于一个Person实体:

ICriteria criteria = currentSession.CreateCriteria<Person>();

可以对这个标准进行操作,以获取想要的结果。如果想要获取所有Person的列表:

currentSession.CreateCriteria(typeof(Person)).List<Person>();

或者可以通过调用实例来实现:

criteria.List<Person>();

如果想要根据ID搜索一个Person,例如:

Person person = currentSession.Get<Person>(id);

或者:

Person person = criteria.Get<Person>(id);

这些结果可以通过应用限制到Criteria查询来过滤。因此,使用Restrictions工厂类,它定义了ICriteria接口上可用的一系列方法,并将它们传递给Add方法。

让看一个例子:

Criteria.Add(Restrictions.Eq("Name", "Rayen"));

或者可以实例化一个新的对象,它具有类型IQueryCriterion限制。

var restrictions = new Conjunction(); restrictions.Add(new LikeCriterion<A>(c => c.Name, "Rayen", true, MatchingMode.Anywhere));

如果想要相等,可以调用第二个方法:

restrictions.Add(new EqualCriterion<A>(c => c.Name, "Rayen"));

这是LikeCriterion方法:

private LikeCriterion(Expression<Func<A, object>> propertyExpression, string value, bool insensitive, MatchingMode matchMode) { PropertyExpression = propertyExpression; Value = value; MatchMode = matchMode; Insensitive = insensitive; } public EqualCriterion(Expression<Func<A, object>> propertyExpression, object value) { PropertyExpression = propertyExpression; Value = value; } var persons = currentSession.CreateCriteria(typeof(Person)).Add(restrictions);

在这个例子中,引入了Expression的概念,它可以被分组。可以使用NHibernate.Expression.Order来排序结果。

var personOrdered = criteria.AddOrder(Order.Asc("Name")).SetMaxResults(100).List<Person>();

可以使用Projections,它使用工厂类NHibernate.Expression.Projections IProjection实例。它通过调用SetProjection()方法来应用。工厂方法允许通过标准和顺序实例引用投影值。

这是一个获取计数的例子:

public int GetCount(IQueryCriterion restrictions) { var criteria = _currentSession.CreateCriteria(typeof(T)).SetProjection(Projections.RowCount); return (int)criteria.UniqueResult(); }

Criteria API在构建动态查询方面非常强大,这有助于提高应用程序中的搜索效率。但是,正如在示例中看到的,属性在criteria查询中是硬编码的。因此,将使用QueryOver来增强criteria查询。

让重写之前的示例,但通过集成QueryOver。

criteria.List<Person>(); criteria.QueryOver<Person>().List(); var persons = currentSession.CreateCriteria(typeof(Person)).Add(restrictions); var persons = currentSession.QueryOver<Person>().Where(restrictions).List();

QueryOver使用Where,它类似于SQL查询,它包括许多特性,例如TransformUsing,它使用提供的IResultTransformer转换结果。

IResultTransformer是一个实现者,它定义了一种策略,用于将criteria查询结果转换为实际应用程序可见的查询结果列表。

可以使用OrderBy

IEnumerable<T> GetAllOrderBy(Expression<Func<T, bool>> restrictions, Expression<Func<T, object>> order, bool ascending = false);

IRepository中有一个方法:

实现将在Repository类中。

public IEnumerable<T> GetAllOrderBy(Expression<Func<T, bool>> restrictions, Expression<Func<T, object>> orderByProperty, bool ascending = false) { var query = currentSession.QueryOver<T>().Where(restrictions); return ascending ? query.OrderBy(orderByProperty).Asc.List() : query.OrderBy(orderByProperty).Desc.List(); }

其中TPerson

var Persons = _personRepository.GetAllOrderBy(e => e.Name == "Rayen", e => e.CreationTime, true);
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485