NHibernate ICriteria查询,包含用于高级搜索的组件和集合

NHibernate ICriteria查询,包含用于高级搜索的组件和集合,nhibernate,fluent-nhibernate,icriteria,Nhibernate,Fluent Nhibernate,Icriteria,我正在为我的ASP.NET MVC应用程序构建高级搜索表单 我有一个客户对象,带有地址组件: Fluent NHibernate映射: public CustomerMap() { WithTable("Customers"); Id(x => x.Id) .WithUnsavedValue(0) .GeneratedBy.Identity(); Map(x =>

我正在为我的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);
        });
在我的客户类ctor中,为了防止空对象,我有以下几点:

public Customer()
{
    Address = new Address();
}
“我的搜索表单”有以下字段可供用户搜索:

  • 客户名称
  • 城市
  • 陈述
  • 工业
所有这些字段都是可选的

我的NHibernate标准如下所示(正在使用ASP.NET MVC模型绑定器从表单传递客户):

行业和州是web表单中的下拉列表,但在上面的示例中,我将它们留空。但是ExcludeZeroes()声明似乎不适用于这些字段

如果我在条件之前手动检查:

if (customer.Address.State == "")
{
    customer.Address.State = null;
}
对工业界也是如此,这样标准就会起作用

我假设这与我在客户ctor中初始化Address对象有关。我不想改变这一点,但我不知道还有什么方法可以让标准在不手动检查表单中的空字符串值的情况下工作(这样就消除了在ICriteria中使用示例对象的优势)。


为什么??如何让这个条件查询工作?

我对QBE也有同样的问题。我还认为,对于对象(和关联对象)的一般搜索,示例查询是一种非常好的方法。已存在ExcludeNones/Nulls/Zero。还应该有一个排除空字符串(“”)的选项。

使用属性选择器忽略空字符串或空字符串

using System;
using NHibernate.Criterion;
using NHibernate.Type;


namespace Sample
{

    /// <summary>
    /// Implementation of <see cref="Example.IPropertySelector"/> that includes the
    /// properties that are not <c>null</c> and do not have an <see cref="String.Empty"/>
    /// returned by <c>propertyValue.ToString()</c>.
    /// </summary>
    /// <remarks>
    /// This selector is not present in H2.1. It may be useful if nullable types
    /// are used for some properties.
    /// </remarks>
    public class NoValuePropertySelector : Example.IPropertySelector
    {
        #region [ Methods (2) ]

        // [ Public Methods (1) ]

        /// <summary>
        /// Determine if the Property should be included.
        /// </summary>
        /// <param name="propertyValue">The value of the property that is being checked for inclusion.</param>
        /// <param name="propertyName">The name of the property that is being checked for inclusion.</param>
        /// <param name="type">The <see cref="T:NHibernate.Type.IType"/> of the property.</param>
        /// <returns>
        ///     <see langword="true"/> if the Property should be included in the Query,
        /// <see langword="false"/> otherwise.
        /// </returns>
        public bool Include(object propertyValue, String propertyName, IType type)
        {
            if (propertyValue == null)
            {
                return false;
            }

            if (propertyValue is string)
            {
                return ((string)propertyValue).Length != 0;
            }

            if (IsZero(propertyValue))
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        // [ Private Methods (1) ]

        private static bool IsZero(object value)
        {
            // Only try to check IConvertibles, to be able to handle various flavors
            // of nullable numbers, etc. Skip strings.
            if (value is IConvertible && !(value is string))
            {
                try
                {
                    return Convert.ToInt64(value) == 0L;
                }
                catch (FormatException)
                {
                    // Ignore
                }
                catch (InvalidCastException)
                {
                    // Ignore
                }
            }

            return false;
        }


        #endregion [ Methods ]
    }

}
使用系统;
使用NHibernate.标准;
使用NHibernate.Type;
名称空间示例
{
/// 
///这方面的实施包括:
///不为null且不具有
///由propertyValue.ToString()返回。
/// 
/// 
///此选择器在H2.1中不存在。如果类型为nullable,则它可能很有用
///用于某些属性。
/// 
公共类NoValuePropertySelector:Example.IPropertySelector
{
#区域[方法(2)]
//[公开方法(1)]
/// 
///确定是否应包括该属性。
/// 
///正在检查是否包含的属性的值。
///正在检查是否包含的属性的名称。
///财产的所有权。
/// 
///如果属性应包括在查询中,
///否则。
/// 
公共bool包括(对象属性值、字符串属性名称、IType类型)
{
if(propertyValue==null)
{
返回false;
}
if(propertyValue为字符串)
{
返回((字符串)propertyValue).Length!=0;
}
if(为零(propertyValue))
{
返回false;
}
其他的
{
返回true;
}
}
//[私人方法(1)]
私有静态布尔值为零(对象值)
{
//仅尝试检查IConvertibles,以便能够处理各种口味
//可为空的数字等。跳过字符串。
if(值是可转换的&&!(值是字符串))
{
尝试
{
返回Convert.ToInt64(值)==0L;
}
捕获(格式化异常)
{
//忽略
}
捕获(无效卡斯特例外)
{
//忽略
}
}
返回false;
}
#端域[方法]
}
}

您喜欢通过示例进行查询吗?不完全是,尽管在高级搜索表单中,它确实使代码更加灵活。如果我检查组件中是否有空字符串并将其更改为null,则可以使上述代码正常工作。我也可以使用HQL并使其工作,但它似乎比必要的更丑陋。我希望QBE能够工作,而不会在代码中添加不必要的检查。
if (customer.Address.State == "")
{
    customer.Address.State = null;
}
using System;
using NHibernate.Criterion;
using NHibernate.Type;


namespace Sample
{

    /// <summary>
    /// Implementation of <see cref="Example.IPropertySelector"/> that includes the
    /// properties that are not <c>null</c> and do not have an <see cref="String.Empty"/>
    /// returned by <c>propertyValue.ToString()</c>.
    /// </summary>
    /// <remarks>
    /// This selector is not present in H2.1. It may be useful if nullable types
    /// are used for some properties.
    /// </remarks>
    public class NoValuePropertySelector : Example.IPropertySelector
    {
        #region [ Methods (2) ]

        // [ Public Methods (1) ]

        /// <summary>
        /// Determine if the Property should be included.
        /// </summary>
        /// <param name="propertyValue">The value of the property that is being checked for inclusion.</param>
        /// <param name="propertyName">The name of the property that is being checked for inclusion.</param>
        /// <param name="type">The <see cref="T:NHibernate.Type.IType"/> of the property.</param>
        /// <returns>
        ///     <see langword="true"/> if the Property should be included in the Query,
        /// <see langword="false"/> otherwise.
        /// </returns>
        public bool Include(object propertyValue, String propertyName, IType type)
        {
            if (propertyValue == null)
            {
                return false;
            }

            if (propertyValue is string)
            {
                return ((string)propertyValue).Length != 0;
            }

            if (IsZero(propertyValue))
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        // [ Private Methods (1) ]

        private static bool IsZero(object value)
        {
            // Only try to check IConvertibles, to be able to handle various flavors
            // of nullable numbers, etc. Skip strings.
            if (value is IConvertible && !(value is string))
            {
                try
                {
                    return Convert.ToInt64(value) == 0L;
                }
                catch (FormatException)
                {
                    // Ignore
                }
                catch (InvalidCastException)
                {
                    // Ignore
                }
            }

            return false;
        }


        #endregion [ Methods ]
    }

}