2009-09-28 11 views
5

Ho il seguente dominio impostato per la persistenza con NHibernate: DomainUso NHibernate Criteria API per selezionare insieme specifico di dati insieme con un conteggio

Sto usando la PaperConfiguration come aggregato radice.

Desidero selezionare tutti gli oggetti PaperConfiguration per un determinato Tier e AcademicYearConfiguration. Funziona molto bene come nell'esempio seguente:

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>(); 

(Forse c'è un modo migliore di farlo però).

Tuttavia, è anche necessario sapere quanti ReferenceMaterials ci sono per ogni PaperConfiguration e vorrei ottenerlo nella stessa chiamata. Evitare HQL - Ho già una soluzione HQL per questo.

So che questo è ciò che le proiezioni sono per e this question suggerisce un'idea ma non riesco a farlo funzionare.

Ho un PaperConfigurationView che ha, invece di IList<ReferenceMaterial> ReferenceMaterials del ReferenceMaterialCount e stava pensando lungo le linee di

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>(); 

purtroppo questo non funziona. Che cosa sto facendo di sbagliato?

La seguente query semplificata:

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 questo SQL piuttosto inaspettata:

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 query sopra non riesce con l'errore ADO.NET in quanto, ovviamente, non è una corretta SQL dal momento che manca un gruppo di o il conteggio è il conteggio (referencem1_.Id) piuttosto che (this_.Id).

mappature 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

Perché la seconda query di criteri non funziona? Qualche messaggio di errore? (Suppongo che manchi una clausola group by, ma voglio essere sicuro di ciò che hai incontrato.) –

+0

Puoi per favore pubblicare i tuoi mapping? –

+0

Domani includerò i mapping per essere sicuro di averli catturati adeguatamente. Per quanto riguarda il messaggio di errore - è possibile vedere dalla query SQL che non sarebbe corretto - ma a questo punto sembra irrilevante dal momento che mi aspetto che un conteggio provenga da una query secondaria ma non ci sono nemmeno JOIN o query secondarie. – mfloryan

risposta

1

Si dovrebbe usare Projections.GroupProperty() al posto di Projections.Property().

+0

Grazie. Ho effettivamente sperimentato questo approccio provando sia Property che GroupProperty ma non produco risultati. – mfloryan

Problemi correlati