2011-07-16 13 views
6

我有一個簡單的方法來嘗試驗證用戶在登錄時的身份,並且我使用Fluent nHibernate來實現持久性,所以我自然實現了ISession.QueryOver<T>來完成此項工作。在nHibernate查詢過程中無法比較字符串<T>

它看起來像下面這樣。

var member = session.QueryOver<Member>() 
    .Where(m => m.Email == Model.Email) 
    .Take(1).SingleOrDefault(); 

好的。那麼,現在的問題。

  1. 電子郵件地址總是需要比較不區分大小寫。

他們應該總是在數據庫中小寫。我爲此付出了巨大的努力。實際上,接受Email Address的我的<input>上有一個驗證規則,只允許小寫字母。但是這還不夠好,我想把它做得更深一些,並且確保一切都是潔淨的。

所以我想這樣做......

var member = session.QueryOver<Member>() 
    .Where(m => String.Compare 
     (m.Email, Model.Email, StringComparison.OrdinalIgnoreCase) == 0) 
    .Take(1).SingleOrDefault(); 

我得到一個異常的NHibernate不能使用String.Compare方法。

我意識到我可以用簡單的ToLower()方法解決這個問題,但可能會出現這種情況,我希望比其他類型的比較更精細一些。

有人可以幫我弄清楚如何解決這個問題嗎?

回答

3

有這樣做的多種方式,與IsInsensitiveLike:

var member= Session.QueryOver<Member>() 
     .WhereRestrictionOn(m=>m.Email).IsInsensitiveLike(Model.Email) 
     .Take(1).SingleOrDefault(); 
+1

像爲v不同的比較語義來平等,這帶來了一整套的安全問題發揮 –

+0

[我的回答](http://stackoverflow.com/a/31404628/11635)更醜陋[但嚴重並沒有讓系統開放用戶名枚舉攻擊] –

1

SQL Server文本匹配不區分大小寫。如果你不喜歡,你必須改變排序規則SQL_Latin1_General_CP1_CS_AS)。所以你不需要改變任何東西(服務器端或客戶端)。

2

如果@扶着默認排序規則和/或specifying an explicit one它不工作的VahidN的回答,可以下降到SQL方言特異性大小寫轉換,像這樣:

return _session.QueryOver<Registration>() 
     .WhereEqualsIgnoreCase(r => r.Name, userName) 
     .Future().SingleOrDefault(); 

實現如下:

static class NHibernateCaseInsensitiveWhereExtensions 
{ 
    public static IQueryOver<T, T2> WhereEqualsIgnoreCase<T, T2>(this IQueryOver<T, T2> that, Expression<Func<T, object>> column, string value) 
    { 
     return 
      that.Where(
       Restrictions.Eq(
        Projections.SqlFunction(
         "upper", 
         NHibernateUtil.String, 
         Projections.Property(column)), 
        value.ToUpper())); 
    } 
}