使用 NHibernate 的示例查询

示例查询最多的应用场合是组合查询,我们常常需要在界面上提供若干的查询选项,然后根据用户的输入返回符合条件的结果。

使用代码直接进行处理往往需要涉及到复杂的条件,由于组合条件并不确定,导致逻辑判断语句结构复杂。对于多个可选的参数,情况会变得更加严重。

使用示例查询可以很方便地处理这种问题。

在查询的时候,将收集到的查询条件赋予一个对象的属性,当然,这个对象的类型就是需要查询的实体对象。

例如,在 NHibernate 中存在一个 User 的类型,我们需要对它的姓名和口令进行组合查询,User 的定义如下:

namespace Demo.Dao.Domain
{
// 用户对象
public class User
{
public virtual int UserId { set; get; }
public virtual string Username { set; get; }
public virtual string Password { set; get; }

public virtual Address Address { set; get; }
}
}

在界面中,我们提供用户输入的输入框。

<p>
<label for="<%= this.tbxName %>">
用户名:</label>
<asp:TextBox ID="tbxName" runat="server"></asp:TextBox>
</p>
<p>
<label for="<%= this.tbxPassword %>">
口令:</label>
<asp:TextBox ID="tbxPassword" runat="server"></asp:TextBox>
</p>
<p>
<asp:Button ID="btnSearch" runat="server" Text="查询" OnClick="btnSearch_Click"/>
</p>

在按钮的点击事件中,我们将用户的输入组合为一个示例对象。然后提交给 NHibernate 进行查询。

protected void btnSearch_Click(object sender, EventArgs e)
{
if (this.IsValid)
{
Demo.Dao.Domain.User example
= new Demo.Dao.Domain.User()
{
Username = this.tbxName.Text,
Password = this.tbxPassword.Text
};
IList<Demo.Dao.Domain.User> list = this.UserService.GetUsers(example);

this.Repeater1.DataSource = list;
this.Repeater1.DataBind();

}
}

在后台的服务中,我们使用示例查询进行处理。

示例查询类型定义在命名空间 NHibernate.Criterion 中,使用静态方法 Create 可以创建示例对象。

首先创建一个查询条件对象,然后使用 Example 的 Create 方法创建出查询示例对象。最后就是实际的查询。

public IList<Demo.Dao.Domain.User> GetUsers( Demo.Dao.Domain.User exampleUser)
{
// 创建查询标准
global::NHibernate.ICriteria criteria
= this.Session.CreateCriteria<Demo.Dao.Domain.User>();

// 创建查询示例
global::NHibernate.Criterion.Example example
= global::NHibernate.Criterion.Example.Create(exampleUser);

// 设置使用示例对象的查询条件
criteria.Add(example);

example.EnableLike(global::NHibernate.Criterion.MatchMode.Anywhere);

IList< Demo.Dao.Domain.User> list = criteria.List<Demo.Dao.Domain.User>();

return list;
}

对于字符串类型的条件来说,默认使用精确匹配,但是,可以通过示例的 EnableLike 进行设置。NHibernate.Criterion.MatchMode 是一个枚举,支持下面的匹配模式。

// 默认字符串是完全匹配,可以通过 EnableLike 进行设置
// Anywhere 表示任何位置匹配
// End 出现在最后位置
// Start 出现在起始位置
// Exact 完全匹配,默认设置
example.EnableLike(global::NHibernate.Criterion.MatchMode.Anywhere);

当在姓名的输入框中输入 a 的时候,NHibernate 生成的 SQL 语句如下:

SELECT this_.UserId as UserId0_0_, this_.Username as Username0_0_, this_.Password as Password0_0_, this_.AddressId as AddressId0_0_ 
FROM
tbl_Users this_
WHERE
(this_.Username like @p0)
 
除了强大的 EnableLike 之外,还提供了几个设置参数,比较常用的有 ExcludeZeroes() 方法,它可以排除属性中值为 0 的属性。
比如,在 User 中增加一个 Age 的整数类型属性,还导致查询语句变成下面的 SQL
SELECT this_.UserId as UserId0_0_, this_.Username as Username0_0_, this_.Password as Password0_0_, 

this_.Age as Age0_0_, this_.AddressId as AddressId0_0_
FROM tbl_Users this_
WHERE (this_.Username like @p0 and this_.Age = @p1)

使用排除 0 的设置
// 排除值为 0 的属性
example.ExcludeZeroes();
现在的 SQL 又成为
SELECT this_.UserId as UserId0_0_, this_.Username as Username0_0_, this_.Password as Password0_0_, 

this_.Age as Age0_0_, this_.AddressId as AddressId0_0_
FROM tbl_Users this_
WHERE (this_.Username like @p0)
不过,还有两个设置就要小心了。
ExcludeNulls() 方法,看起来是排除值为 null 的属性,不过,代码中是先调用了 ToString() 方法,然后再看字符串的长度,所以会使得前面的 ExcludeZeroes() 失效。
SELECT this_.UserId as UserId0_0_, this_.Username as Username0_0_, this_.Password as Password0_0_, 

this_.Age as Age0_0_, this_.AddressId as AddressId0_0_
FROM tbl_Users this_
WHERE (this_.Username like @p0 and this_.Age = @p1)
ExcludeNone() 方法,表示需要使用示例对象的所有属性,也会使得 ExcludeZeroes() 失效。
SELECT this_.UserId as UserId0_0_, this_.Username as Username0_0_, this_.Password as Password0_0_, 

this_.Age as Age0_0_, this_.AddressId as AddressId0_0_
FROM tbl_Users this_
WHERE (this_.Username like @p0 and this_.Password is null and this_.Age = @p1)

最后,还有一个 IgnoreCase() 方法, 使用不区分大小写的方法比较字符串,对于 Oracle 是有效的,对于 SQL Server 就用不到了。
SELECT this_.UserId as UserId0_0_, this_.Username as Username0_0_, this_.Password as Password0_0_, 

this_.Age as Age0_0_, this_.AddressId as AddressId0_0_
FROM tbl_Users this_
WHERE (lower(this_.Username) like lower(@p0) and this_.Age = @p1)
原文地址:https://www.cnblogs.com/haogj/p/2255848.html