2009-09-28 10 views
5

mam następujące domeny skonfigurowane do utrzymywania się z NHibernate: DomainKorzystanie NHibernate Criteria API, aby wybrać określony zestaw danych wraz z liczbą

Używam PaperConfiguration jako kruszywo korzeniowego.

Chcę wybrać wszystkie obiekty PaperConfiguration dla danego poziomu i AcademicYearConfiguration. Działa to bardzo dobrze, jak w poniższym przykładzie:

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

(Być może jest lepszy sposób to zrobić).

Należy również wiedzieć, ile materiałów referencyjnych jest dostępnych dla każdej konfiguracji PaperConfiguration i chciałbym uzyskać je w tym samym wywołaniu. Unikaj HQL - już mam do tego rozwiązanie HQL.

Wiem, do czego służą prognozy, a this question sugeruje pomysł, ale nie mogę go uruchomić.

Mam PaperConfigurationView który ma zamiast IList<ReferenceMaterial> ReferenceMaterials ReferenceMaterialCount i myślał wzdłuż linii

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

niestety to nie działa. Co ja robię źle?

Następująca kwerenda uproszczony:

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

tworzy to raczej nieoczekiwane SQL:

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

Powyższa kwerenda nie powiedzie się z powodu błędu ADO.NET, gdyż oczywiście nie jest poprawny SQL, ponieważ brakuje liczona jest grupa lub liczba (referencem1_.Id), a nie (this_.Id).

NHibernate mapowania:

<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

Dlaczego drugie zapytanie o kryteria nie działa? Jakieś komunikaty o błędach? (Zakładam, że brakuje w nim klauzuli group by, ale chcę mieć pewność, co napotkasz.) –

+0

Czy możesz opublikować swoje mapowania? –

+0

Będę uwzględniał jutro mapowania, aby upewnić się, że je odpowiednio przechwyciłem. Odnośnie komunikatu o błędzie - widać z zapytania SQL, że nie jest ono poprawne - ale w tym momencie wydaje się nieistotne, ponieważ oczekiwałbym, że licznik pochodzi z sub zapytania, ale nie ma tam nawet JOIN ani sub zapytania. – mfloryan

Odpowiedz

1

Należy użyć Projections.GroupProperty() zamiast Projections.Property().

+0

Dziękuję. Rzeczywiście eksperymentowałem z tym podejściem, próbując zarówno Property, jak i GroupProperty, ale ani nie przynosząc rezultatów. – mfloryan