2011-07-16 13 views
6

Tengo un método simple para tratar de validar a los usuarios cuando inician sesión, y uso Fluent nHibernate para la persistencia, así que naturalmente implemente ISession.QueryOver<T> para hacer este trabajo.No se pueden comparar cadenas durante nHibernate QueryOver <T>

Parece lo siguiente.

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

Ok. Entonces, los problemas a mano.

  1. Las direcciones de correo electrónico siempre deben compararse entre mayúsculas y minúsculas.

They should siempre en la base de datos como minúsculas. Me he esforzado mucho para que esto suceda. Y, de hecho, mi <input> que acepta Email Address tiene una regla de validación para permitir letras minúsculas. Pero eso aún no es lo suficientemente bueno, quiero hacer esto aún más profundo y estar absolutamente seguro de que todo es Kosher.

así que he intentado hacer esto ...

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

me sale una excepción que nhibernate no puede utilizar el método String.Compare.

Me doy cuenta de que puedo resolver esto con el simple método ToLower(), pero puede haber situaciones en las que quiero un poco más de granularidad con respecto a otros tipos de comparaciones.

¿Alguien me puede ayudar a encontrar la manera de evitar esto?

Respuesta

3

Hay varias maneras de hacer esto, con un IsInsensitiveLike:

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

Al igual que tiene v Diferentes semánticas de comparación para iguales, y esto trae un conjunto completo de preocupaciones de seguridad en juego –

+0

[mi respuesta] (http://stackoverflow.com/a/31404628/11635) es mucho más fea [pero no deja el sistema abierto para nombre de usuario enumerationm ataques] –

1

SQL Server Text Matching Is Case INSENSITIVE. Si no le gusta, debe cambiar la clasificación (SQL_Latin1_General_CP1_CS_AS). Por lo tanto, no necesita cambiar nada (desde el lado del servidor o desde el lado del cliente).

2

Si @ respuesta de apoyarse en la colación por defecto y/o specifying an explicit one no funciona de VahidN, uno puede caer a SQL-dialecto conversión caso específico de este modo:

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

Implementado como sigue:

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())); 
    } 
} 
Cuestiones relacionadas