示例查询最多的应用场合是组合查询,我们常常需要在界面上提供若干的查询选项,然后根据用户的输入返回符合条件的结果。
使用代码直接进行处理往往需要涉及到复杂的条件,由于组合条件并不确定,导致逻辑判断语句结构复杂。对于多个可选的参数,情况会变得更加严重。
使用示例查询可以很方便地处理这种问题。
在查询的时候,将收集到的查询条件赋予一个对象的属性,当然,这个对象的类型就是需要查询的实体对象。
例如,在 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)
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 的属性
example.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)
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)
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)
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)