2009-05-21 37 views
2

我正在爲我的ASP.NET MVC應用程序構建高級搜索表單。用於高級搜索的NHibernate ICriteria查詢與組件和集合

我有一個客戶對象,具有地址組件: 功能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); 
     }); 

在我的Customer類構造函數,以防止空的對象,我有以下幾點:

public Customer() 
{ 
    Address = new Address(); 
} 

我的搜索表單有以下字段可供用戶搜索:

  • Cus Tomer的名稱
  • 國家
  • 產業

所有這些領域都是可選的。

我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()排除空和零缺省值。這是必需的,因爲我的Customer對象有一些INT(爲了簡潔起見,在這篇文章中被排除),它會在查詢中默認爲零,導致不正確的查詢。

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表單的下拉列表,但:

如果我與所有空(OK,因爲它們是可選的),生成的SQL看起來像這樣的字段運行此在上面的例子中,我將它們留爲空白。但ExcludeZeroes()聲明似乎不適用於這些字段。

如果我手動檢查標準之前:

if (customer.Address.State == "") 
{ 
    customer.Address.State = null; 
} 

和做產業一樣,標準將隨後工作。

我假設這與我初始化我的客戶ctor中的地址對象有關。我討厭改變這一點,但我不知道如何在沒有手動檢查表單中的空字符串值的情況下使Criteria工作的另一種方式(從而消除了使用ICriteria使用Example對象的優勢)。

爲什麼?我怎樣才能使這個標準查詢工作?

+0

你是否結婚了Query By Example? – 2009-05-22 00:54:10

回答

1

使用屬性選擇器忽略空字符串或空字符串。

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 ] 
    } 

} 
0

我與QBE有同樣的問題。我也認爲按實例查詢是對對象(和關聯)的通用搜索非常好的方法。已經有ExcludeNones/Nulls/Zeros。應該有一個選項來排除空字符串(「」)。