¿Puedo consultar un UserType con varias propiedades asignadas a una sola columna?

StackOverflow https://stackoverflow.com/questions/5845693

  •  27-10-2019
  •  | 
  •  

Pregunta

Tengo el siguiente modelo de dominio:

public class Name
{
    private readonly string fullName;
    public Name(string fullName) { this.fullName = fullName }
    public string FullName { get { return fullName; } }
    public string FirstName { get { /* ... */ } }
    public string MiddleNames { get { /* ... */ } }
    public string LastName { get { /* ... */ } }
    public static implicit operator Name(string name) { /* ... */ }
}

public class Person
{
    public Name BirthName { get; set; }
    public Name Pseudonym { get; set; }
}

Implementé IUserType Por lo tanto, puedo asignar cada nombre a una sola columna de base de datos con el nombre completo.

Consultas como este trabajo:

var people = session.QueryOver<Person>()
                    .Where(p => p.Name == "John Doe")
                    .List();

Pero no puedo consultar así:

var people = session.QueryOver<Person>()
                    .Where(p => p.Name.LastName == "Doe")
                    .List();

¿Puedo hacer que Nhibernate funcione con esto?

¿Fue útil?

Solución

No soy un gran usuario nhibernado, pero analizando toda la información que tenemos aquí sobre el escenario, tengo la sensación de que la respuesta es que no puedes.

Está mapeando el valor contenido en esa clase a un solo valor en el DB.

Para que permita la consulta en sus piezas, tendría que comprender cómo todas esas sub piezas de información en la clase de nombre están relacionadas con el valor completo.

Eso significaría comprender lo que está haciendo el código C# personalizado que tiene.


Actualización 1:

La respuesta anterior es con respecto a tenerlo todo generado automáticamente para usted y usar la consulta exacta que mencionó allí.

Definitivamente puede solucionar el problema como sugerido por @CS. Es decir, definir una función definida por el usuario que hace lo que desea y mapear eso en nHibernate.

Por lo menos eso te permitiría hacer algo como:

session.QueryOver<Person>()
        .Where(p => session.PersonLastName(p) == "Doe")
        .List();

Otra forma sería definir un método de extensión que se traduzca a lo que desea, implementándolo en este artículo: http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html

El uso entonces sería como:

 session.QueryOver<Person>()
     .Where(p=> p.Name.LastNameExt() == "Doe")// Ext just to avoid name collision
     .List();

Finalmente, no estoy seguro de si es posible mapear las propiedades sub de propiedad a las funciones definidas por el usuario para cada una, para que su consulta pueda permanecer sin cambios como:

 session.QueryOver<Person>()
                .Where(p => p.Name.LastName == "Doe")
                .List();

No es que en todos los casos esté cambiando de concatenar datos a datos de análisis. Usted es el único que sabe si eso realmente le está comprando algo, en lugar de mantener las propiedades por separado.

Otros consejos

Creo que es posible, pero requerirá algo de trabajo en el lado SQL de las cosas. Lo primero que probablemente intentaría es crear un UDF de algún tipo que divida el nombre para usted y haga la comparación necesaria. Luego puede extender nHibernate para asignar a este UDF y usted debería Ser capaz de invocar esta función desde su consulta, ya sea SQL, HQL o ICriterios basados.

Solo podrá consultar contra el nombre completo, debido a que es solo un campo de base de datos.

Si lo asigna de manera diferente para que FirstName y LastName sean columnas separadas, debe poder consultar en cada uno de ellos, pero entonces puede tener dificultades para consultar una propiedad llamada Nombre FullName.

Necesita crear columnas calculadas. Serán de solo lectura pero puedes consultar contra ellos. Ver aquí.

Lo que podría hacer es implementar su propio envoltorio de repositorio para estos objetos e implementar métodos como getUsersByLastName () que podría usar HQL para realizar este tipo de consultas de "búsqueda por valor parcial".

Algo como lo siguiente debería permitirle buscar por cualquier valor parcial siempre que pase en la cadena de búsqueda correcta:

var hql = "select p from People p where lower(p.BirthName) like :searchText";

Editar:

Eliminado LastName de la consulta. La forma en que funcionaría es que utilizaría el texto de búsqueda anclado al comienzo o al final del campo Nombre de nacimiento. Por ejemplo, si quisieras buscar a todas las personas con apellidos de Smith, podrías hacer:

var hql = "select p from People p where lower(p.BirthName) like '% smith'";

Y en el caso de personas con primer nombre Joe:

var hql = "select p from People p where lower(p.BirthName) like 'joe %'";
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top