2010-05-27 39 views
1

我正在開發一個應該允許對數據庫進行基本搜索的小項目。 目前我正在使用nhibernate進行數據庫交互。 在數據庫中我有2個表格:Person和Address。 Person表與Address有多對一的關係。如何使用nhibernate進行正確的搜索

代碼中,我想出了做搜索是:

public IList<T> GetByParameterList(List<QueryParameter> parameterList) 
    { 
     if (parameterList == null) 
     { 
      return GetAll(); 
     } 
     using (ISession session = NHibernateHelper.OpenSession()) 
     { 
      ICriteria criteria = session.CreateCriteria<T>(); 
      foreach (QueryParameter param in parameterList) 
      { 
       switch (param.Constraint) 
       { 
        case ConstraintType.Less: 
         criteria.Add(Expression.Lt(param.ParameterName, param.ParameterValue)); 
         break; 
        case ConstraintType.More: 
         criteria.Add(Expression.Gt(param.ParameterName, param.ParameterValue)); 
         break; 
        case ConstraintType.LessOrEqual: 
         criteria.Add(Expression.Le(param.ParameterName, param.ParameterValue)); 
         break; 
        case ConstraintType.EqualOrMore: 
         criteria.Add(Expression.Ge(param.ParameterName, param.ParameterValue)); 
         break; 
        case ConstraintType.Equals: 
         criteria.Add(Expression.Eq(param.ParameterName, param.ParameterValue)); 
         break; 
        case ConstraintType.Like: 
         criteria.Add(Expression.Like(param.ParameterName, param.ParameterValue)); 
         break; 
       } 
      } 

      try 
      { 
       IList<T> result = criteria.List<T>(); 
       return result; 
      } 
      catch 
      { 
       //TODO: Implement some exception handling 
       throw; 
      } 
     } 
    } 

的查詢參數是,我用它來創建指標分析,並將其發送到DAL輔助對象,它看起來像這樣:

public class QueryParameter 
{ 
    public QueryParameter(string ParameterName, Object ParameterValue, ConstraintType constraintType) 
    { 
     this.ParameterName = ParameterName; 
     this.ParameterValue = ParameterValue; 
     this.Constraint = constraintType; 
    } 

    public string ParameterName 
    { 
     get; 
     set; 
    } 

    public Object ParameterValue 
    { 
     get; 
     set; 
    } 

    public ConstraintType Constraint 
    { 
     get; 
     set; 
    } 
} 

現在,如果我正在做一個像FirstName =「John」這樣的搜索,但不是當我嘗試給出一個像Street =「Some Street」這樣的參數時,效果很好。看來,nhibernate正在尋找Person表中的街道列,但不是在Address表中尋找。

任何想法應該如何改變我的代碼,以便我可以做一個適當的搜索?提示?也許有些替代品?

聲明:我是一個菜鳥,所以請溫柔;) 謝謝,丹尼斯。

回答

0

它正在尋找在Person實體街物業(ORM通知......語言沒有表和列;-)),因爲這行:

ICriteria criteria = session.CreateCriteria<T>(); 

我假設你的類型T是Person,因此您的標準假設您添加的約束指向Person中的屬性。

如果您傳遞的參數是地址實體上的過濾器,則需要撥打CreateAlias(...)以「加入」地址。

+0

事情是我真的不知道用戶正在搜索什麼,直到我收到搜索請求。我希望能夠使這種搜索通用(例如,如果我添加一些新的實體到域中,所以我不必更改代碼)。有什麼辦法可以告訴nhibernate做一個「級聯」(我不知道這是正確的詞)搜索? – 2010-05-27 17:13:33

+0

我不認爲NHibernate(或任何ORM ......但我可能是錯的)可以爲你做這個。我建議你修改你的QueryParameter類和GetByParameterList方法來支持指定參數實際存在的子實體(如果它在主實體上不存在)。 – 2010-05-27 17:26:22

+0

此外,您可能期望NHibernate爲您做的太多。它需要檢查所有主要實體的關聯是否存在該屬性......但是,那麼您希望它遞歸地遍歷整個對象樹來尋找屬性嗎?如果這樣做對你來說可能是很好的,但它看起來會對性能造成太大的影響。 – 2010-05-27 17:32:12

0

你可以使用一個HQL這樣的查詢

from Person p join Address a where a.Street = :street 

,並設置:與查詢街道參數。

我發現使用hql比處理標準的東西要容易得多,特別是當你是新手。你的第一本能是標準化你的nhibernate用法,但是當你學習它的時候,最好讓你的代碼接近nhibernate API並且不要寫太多的幫助器方法。

+0

我同意來了。在你非常熟悉NHibernate之前,等待爲你自己創建一個助手框架是很好的。 – 2010-05-27 17:58:09

1

我會爲每個我的域對象類(例如使用針對我的域對象的代碼生成)做強類型搜索類。

我將有一個抽象類來將ICriteriaBuilder邏輯使用非常接近您當前的代碼,然後對任何內部ICriteriaBuilder屬性進行遞歸。

我將有類似的東西僞代碼:

class SearchCriteriaBuilder 
public ConstraintType constraintType 
public ICriteria Build(ISearchCriteriaBuilder pSearchCriteria) 
{'your code goes there'} 

class AdressSearchCriteriaBuilder : SearchCriteriaBuilder 
public StringSearchCriteriaBuilder street; 
public IntegerSearchCriteriaBuilder number; 

class PersonSearchCriteriaBuilder : SearchCriteriaBuilder 
public StringSearchCriteriaBuilder name; 
public AdressSearchCriteriaBuilder adress; 
+0

好吧,我明白你的觀點。事情是我需要我的系統從映射文件自動生成域對象類。所以如果有人添加了一些映射文件,下次啓動時會生成DO類。而增加一些更多的自動啓動功能會使啓動非常緩慢。這就是爲什麼我希望寫一個適合他們所有的代碼。我不知道它是否是最好的解決方案,但是它起作用(我改變了queryparameter類)並且對於一個足夠好的學校項目來說。 – 2010-06-01 12:18:06

+0

運行時的代碼生成會被終止。我打算在開發時做代碼生成。每次數據庫模式更改時,您都應該重新編譯二進制文件幷包含映射。 看看db2hbm和hbm2net並修改hbm2net。修改hbm2net以生成do和某些queryparameter派生類似乎是非常可行的。你可以在這裏獲得源代碼。 http://www.felicepollano.com/2010/05/24/Hbm2netAndDb2hbmSourceCodeLocation.aspx – 2010-06-05 14:07:29