2011-04-23 10 views
7

estoy tratando de generar SQL a lo largo de las líneas de:NHIbernate: ¿atajo para proyectar todas las propiedades?

SELECT 
    t.*, 
    SELECT (...) 
FROM Title t 
[trimmed] 

usando QueryOver

Title title = null; 

var q = session 
    .QueryOver(() => title) 
    .Select(
     Projections.Alias(Projections.Property<Title>(t => t.Id), "Id"), 
     Projections.Alias(Projections.Property<Title>(t => t.Name), "Name"), 
     .... 
     Projections.SubQuery(sq.Where(tt => tt.Id == title.Id))), "TopLevelGenre") 
) 
[code trimmed] 

Hay 15 propiedades en el título que me gustaría proyectar. ¿Hay una manera más fácil de hacerlo para no tener que proyectar cada propiedad individualmente como he comenzado a hacer arriba?

+0

Supongo que no quiere utilizar 'HQL'? – Rippo

+0

Prefiero ICriteria, pero estoy abierto a usar HQL. ¿Qué tenías en mente? – csano

+0

Además, si el código que publiqué arriba es la única manera de hacerlo con ICritiera, agradecería la confirmación. – csano

Respuesta

2

Descubrí que a partir de NHibernate 3.2, esto no es posible sin enumerar manualmente todas las propiedades.

0

Si desea que los objetos de título, sólo se puede escribir:

IList<Title> list = session.QueryOver<Title>.Where(/*some condition*/).List(); 

NHibernate rellenará todos los atributos title para usted.
ver here para más detalles.

+0

gracias por su respuesta. Esto no es lo que estoy buscando, sin embargo. Como puede ver en el código que publiqué, estoy tratando de seleccionar todos los valores en la tabla de título además de un valor generado por la subconsulta. – csano

0

¿Es posible crear una vista en la tabla de títulos con las columnas que le interesan? o Quizás desee intentar dividir las propiedades de la clase Title en dos clases (clase TitleBase y clase Title que se hereda de la clase TitleBase). En consecuencia, debe crear dos archivos de mapeo separados.

Suponga que si todas las propiedades que le interesan están en la clase TitleBase, entonces úselas en la consulta mencionada anteriormente.

1

Si no te importa ICriteria, esto funciona. He probado con 2.1.2, pero no puedo ver por qué si no funciona con 3.x.

var projectionList = Projections.ProjectionList(); 
var metadata = session.SessionFactory.GetClassMetadata(typeof(Title)); 
foreach (var name in metadata.PropertyNames) 
{ 
    projectionList.Add(Projections.Property(name), name); 
} 
var criteria = DetachedCriteria.For<Title>() 
    .SetProjection(projectionList) 
    ...; 
1

No es posible hacerlo sin enumerar manualmente todas las propiedades. Usualmente uso CodeSmith para generar códigos de proyección.

0

Lo he resuelto con este código. Espero que pueda servirte. Solo uso Bags, simplemente cambio la comparación si necesita usar ISet por ejemplo. PDM es una entidad cuyas propiedades estoy aplicando reflexión. Puede cambiar este método para que sea genérico.

 ProjectionList list = Projections.ProjectionList();    
     var metadata = session.SessionFactory.GetClassMetadata(typeof(PDM)); 

     foreach (var name in metadata.PropertyNames) 
     { 
      PropertyInfo property = typeof(PDM).GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name)); 
      FieldInfo field = typeof(PDM).GetFields(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name)); 

      if (property != null) 
      { 
       if (!property.PropertyType.Name.Contains("IList")) 
       { 
        list.Add(Projections.Property(name), name); 
       } 
      } 

      if (field != null) 
      { 
       if (!field.FieldType.Name.Contains("IList")) 
       { 
        list.Add(Projections.Property(name), name); 
       } 
      } 
     }   
Cuestiones relacionadas