我正在为我的ASP.NET MVC应用程序构建高级搜索表单。
我有一个客户对象,带有地址组件:
Fluent NHibernate映射:
public CustomerMap()
{
WithTable("Customers");
Id(x => x.Id)
.WithUnsavedValue(0)
.GeneratedBy.Identity();
Map(x => x.Name);
Map(x => x.Industry);
Component(x => x.Address, m =>
{
m.Map(x => x.AddressLine);
m.Map(x => x.City);
m.Map(x => x.State);
m.Map(x => x.Zip);
});
public Customer()
{
Address = new Address();
}
“我的搜索表单”有以下字段可供用户搜索:
所有这些字段都是可选的。
我的NHibernate标准如下所示(正在使用ASP.NET MVC模型绑定器从表单传递客户):
var p = Session.CreateCriteria(typeof(Customer))
.Add(Example.Create(customer).ExcludeZeroes().IgnoreCase().EnableLike())
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("Id"), "Id")
.Add(Projections.Property("Name"), "Name")
.Add(Projections.Property("Address.City"), "City")
.Add(Projections.Property("Address.State"), "State")
.Add(Projections.Property("PhoneNumber"), "PhoneNumber"))
.AddOrder(Order.Asc("Name"))
.SetResultTransformer(NHibernate.Transform.Transformers.AliasToBean(typeof(CustomerDTO)));
return p.List<CustomerDTO>() as List<CustomerDTO>;
请注意,我使用.ExcludeZeroes()来排除null和零默认值。这是必需的,因为我的客户对象有一些int(为了简洁起见,本文中排除了这些int),这些int在查询中会默认为零(0),从而导致不正确的查询。
如果在所有字段都为空的情况下运行此操作(确定,因为它们是可选的),则生成的SQL如下所示:
SELECT this_.Id as y0_,
this_.Name as y1_,
this_.City as y2_,
this_.State as y3_,
this_.PhoneNumber as y4_
FROM Customers this_
WHERE (lower(this_.Industry) like '' /* @p0 */
and lower(this_.State) like '' /* @p1 */)
ORDER BY y1_ asc
行业和州是web表单中的下拉列表,但在上面的示例中,我将它们留空。但是ExcludeZeroes()声明似乎不适用于这些字段。
如果我在条件之前手动检查:
if (customer.Address.State == "")
{
customer.Address.State = null;
}
对工业界也是如此,这样标准就会起作用。
我假设这与我在客户ctor中初始化Address对象有关。我不想改变这一点,但我不知道还有什么方法可以让标准在不手动检查表单中的空字符串值的情况下工作(这样就消除了在ICriteria中使用示例对象的优势)。
为什么?如何使此条件查询工作?