Pregunta

Estoy usando una consulta con nombre personalizada con NHibernate que quiero devolver una colección de objetos Persona. El objeto Person no está asignado con una asignación de NHibernate, lo que significa que obtengo la siguiente excepción:

  

System.Collections.Generic.KeyNotFoundException:   La clave dada no estaba presente en el   diccionario.

Se genera cuando se crea la sesión porque no puede encontrar el nombre de la clase cuando llama a NHibernate.Cfg.Mappings.GetClass (String className). Todo esto es bastante comprensible, pero me preguntaba si había alguna forma de decirle a NHibernate que usara la clase a pesar de que no tengo un mapeo para ella.

¿Fue útil?

Solución 5

Para resolver esto, terminé usando TupleToPropertyResultTransformer y proporcioné la lista de valores de propiedad. Hay algunas limitaciones para esto, la principal es que la consulta SQL debe devolver los resultados en el mismo orden en que proporciona sus propiedades al constructor TupleToPropertyResultTransformer.

También se infieren los tipos de propiedad, por lo que debe tener cuidado con las columnas decimales que solo devuelven valores enteros, etc. Aparte de eso, usar TupleToPropertyResultTransformer proporcionó una forma razonablemente fácil de usar una consulta SQL para devolver una colección de objetos sin asignar explícitamente objetos dentro de NHibernate.

Otros consejos

¿Por qué no usas?

query.SetResultTransformer(Transformers.AliasToBean(typeof(Person)));

Insertará datos de cada columna en su consulta en las propiedades del objeto Persona usando un alias de columna como nombre de propiedad.

¿Cómo puede crear una consulta que devuelva instancias de un tipo que no está asignado?

Creo que Michal tiene razón aquí, y tal vez deberías echar un vistazo a las proyecciones. (Al menos, esto es lo que creo que estás buscando).

Usted crea una consulta en algún tipo mapeado y luego puede 'proyectar' esa consulta en un 'DTO'. Para hacer esto, tendrá que 'importar' su clase Person, para que NHibernate la conozca, y deberá usar un ResultTransformer.

Algo como esto:

ICriteria crit = session.CreateCriteria (typeof(Person));

// set some filter criteria

crit.SetProjection (Projections.ProjectionList()
                     .Add (Property("Name"), "Name")
                     .Add (Property( ... )
                   );

crit.SetResultTransformer(Transformers.AliasToBean(typeof(PersonView));

return crit.List<PersonView>();

Pero, esto todavía significa que tendrá que importar la clase, para que NHibernate lo sepa.

Al usar la clase, NHibernate básicamente estaría adivinando acerca de todo lo relacionado, incluida la tabla que pretendía usar para Person y las asignaciones de campo. NHibernate probablemente podría ser pirateado para hacer un enlace dinámico basado en la coincidencia de los nombres o algo así, pero la idea es crear las asignaciones de objetos de datos antiguos a los campos de la base de datos utilizando los archivos xml.

Si no hay una buena razón para no asignar la clase, simplemente agregando la asignación le dará los mejores resultados ...

Dicho esto, no puede usar una consulta con nombre para inyectar resultados directamente en una clase no asignada. Debería decirle qué columnas colocar en qué campos o, en otras palabras, un mapeo. ;) Sin embargo, puede devolver valores escalares de una consulta con nombre y podría tomar esas matrices de objetos y construir su colección manualmente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top