2009-09-28 8 views
5

tengo el siguiente dominio establecido para la persistencia con NHibernate: Domainlos criterios del API para seleccionar conjunto específico de datos junto con un recuento

estoy usando el PaperConfiguration como la suma de la raíz.

Quiero seleccionar todos los objetos PaperConfiguration para un Nivel determinado y AcademicYearConfiguration. Esto funciona muy bien como en el siguiente ejemplo:

ICriteria criteria = 
session.CreateCriteria<PaperConfiguration>() 
    .Add(Restrictions.Eq("AcademicYearConfiguration", configuration)) 
    .CreateCriteria("Paper") 
    .CreateCriteria("Unit") 
    .CreateCriteria("Tier") 
     .Add(Restrictions.Eq("Id", tier.Id)) 

return criteria.List<PaperConfiguration>(); 

(aunque hay una forma mejor de hacerlo).

Pero también necesito saber cuántos ReferenceMaterials hay para cada PaperConfiguration y me gustaría obtenerlo en la misma llamada. Evite HQL: ya tengo una solución HQL para ello.

Sé que esto es para lo que son las proyecciones y this question sugiere una idea, pero no puedo hacer que funcione.

Tengo un PaperConfigurationView que tiene, en lugar de la IList<ReferenceMaterial> ReferenceMaterials ReferenceMaterialCount y estaba pensando en la línea de

ICriteria criteria = 
session.CreateCriteria<PaperConfiguration>() 
    .Add(Restrictions.Eq("AcademicYearConfiguration", configuration)) 
    .CreateCriteria("Paper") 
    .CreateCriteria("Unit") 
    .CreateCriteria("Tier") 
     .Add(Restrictions.Eq("Id", tier.Id)) 
    .SetProjection(
     Projections.ProjectionList() 
      .Add(Projections.Property("IsSelected"), "IsSelected") 
      .Add(Projections.Property("Paper"), "Paper") 
      // and so on for all relevant properties 
      .Add(Projections.Count("ReferenceMaterials"), "ReferenceMaterialCount") 
    .SetResultTransformer(Transformers.AliasToBean<PaperConfigurationView>()); 

return criteria.List<PaperConfigurationView>(); 

lamentablemente esto no funciona. ¿Qué estoy haciendo mal?

La siguiente consulta simplificada:

ICriteria criteria = 
session.CreateCriteria<PaperConfiguration>() 
.CreateCriteria("ReferenceMaterials") 
.SetProjection(
Projections.ProjectionList() 
.Add(Projections.Property("Id"), "Id") 
.Add(Projections.Count("ReferenceMaterials"), "ReferenceMaterialCount") 
).SetResultTransformer(Transformers.AliasToBean<PaperConfigurationView>()); 
return criteria.List<PaperConfigurationView>(); 

crea este SQL bastante inesperado:

SELECT 
    this_.Id as y0_, 
    count(this_.Id) as y1_ 
FROM Domain.PaperConfiguration this_ 
    inner join Domain.ReferenceMaterial referencem1_ 
    on this_.Id=referencem1_.PaperConfigurationId 

La consulta anterior falla con el error ADO.NET, ya que, obviamente, no es un SQL correcta, ya que no se encuentra un grupo por o el recuento que es recuento (referencem1_.Id) en lugar de (this_.Id).

asignaciones de NHibernate:

<class name="PaperConfiguration" table="PaperConfiguration"> 
    <id name="Id" type="Int32"> 
     <column name="Id" sql-type="int" not-null="true" unique="true" index="PK_PaperConfiguration"/> 
     <generator class="native" /> 
    </id> 
    <!-- IPersistent --> 
    <version name="VersionLock" /> 
    <!-- IAuditable --> 
    <property name="WhenCreated" type="DateTime" /> 
    <property name="CreatedBy" type="String" length="50" /> 
    <property name="WhenChanged" type="DateTime" /> 
    <property name="ChangedBy" type="String" length="50" /> 

    <property name="IsEmeEnabled" type="boolean" not-null="true" /> 

    <property name="IsSelected" type="boolean" not-null="true" /> 

    <many-to-one name="Paper" column="PaperId" class="Paper" not-null="true" access="field.camelcase"/> 

    <many-to-one name="AcademicYearConfiguration" column="AcademicYearConfigurationId" class="AcademicYearConfiguration" not-null="true" access="field.camelcase"/> 

    <bag name="ReferenceMaterials" generic="true" cascade="delete" lazy="true" inverse="true"> 
     <key column="PaperConfigurationId" not-null="true" /> 
     <one-to-many class="ReferenceMaterial" /> 
    </bag> 
    </class> 

    <class name="ReferenceMaterial" table="ReferenceMaterial"> 
    <id name="Id" type="Int32"> 
     <column name="Id" sql-type="int" not-null="true" unique="true" index="PK_ReferenceMaterial"/> 
     <generator class="native" /> 
    </id> 
    <!-- IPersistent --> 
    <version name="VersionLock" /> 
    <!-- IAuditable --> 
    <property name="WhenCreated" type="DateTime" /> 
    <property name="CreatedBy" type="String" length="50" /> 
    <property name="WhenChanged" type="DateTime" /> 
    <property name="ChangedBy" type="String" length="50" /> 

    <property name="Name" type="String" not-null="true" /> 
    <property name="ContentFile" type="String" not-null="false" /> 
    <property name="Position" type="int" not-null="false" /> 
    <property name="CommentaryName" type="String" not-null="false" /> 
    <property name="CommentarySubjectTask" type="String" not-null="false" /> 
    <property name="CommentaryPointScore" type="String" not-null="false" /> 
    <property name="CommentaryContentFile" type="String" not-null="false" /> 

    <many-to-one name="PaperConfiguration" column="PaperConfigurationId" class="PaperConfiguration" not-null="true"/> 
    </class> 
+0

¿Por qué la segunda consulta de criterios no funciona? Cualquier mensaje de error? (Supongo que falta una cláusula group by, pero quiero asegurarme de lo que encontraste). –

+0

¿Puedes publicar tus mapeos? –

+0

Incluiré las asignaciones mañana para asegurarme de haberlas capturado adecuadamente. En cuanto al mensaje de error (puede ver que no es correcto en la consulta SQL), en este punto parece irrelevante, ya que esperaría que un recuento fuera de una consulta secundaria, pero ni siquiera hay ENTRADA ni sub consulta. – mfloryan

Respuesta

1

Debe utilizar Projections.GroupProperty() en lugar de Projections.Property().

+0

Gracias. De hecho, he experimentado con este enfoque al probar Property y GroupProperty pero tampoco arrojar resultados. – mfloryan

Cuestiones relacionadas