2012-04-11 9 views
7

Ich muss die Anzahl der Zeilen aus einer Kriterienabfrage und die Kriterien erhalten Gruppe von Projektionen. (benötigt, um Paging zur Arbeit zu bringen)NHibernate, erhalten rowcount wenn Kriterien haben eine Gruppe von

z.

Ich muss CreateSQL vermeiden, da ich viele Kriterien habe .. und die Einschränkungen usw. sind komplex.

Können Sie ein Unterkriterium (losgelöst) und dann select count(*) from ..? Kann nicht herausfinden, wie?

EDIT: Ich löste es, indem ich die SQL aus den Kriterien und dann ändern, so dass es jetzt funktioniert! GetSql from criteria

+0

Ich möchte das gleiche tun ... aber vermeiden Sie die GetSql-Lösung. –

+0

Ja, diese Lösung war schmerzhaft, benötigt, um die SQL aus den Kriterien zu bekommen, aber Sie können nicht die Parameter Typen oder Werte aus den Kriterien (auf einfache Weise), so dass wir eine andere Sammlung benötigt, um die Werte zu speichern, und sie müssen in der richtigen Reihenfolge usw. sein. –

+0

Was hast du eigentlich in SQL geschrieben? Ich verstehe immer noch nicht, welches Ergebnis du brauchst. –

Antwort

0

Ich denke, das kann mit NH Multi Queries getan werden.

Hier sind einige Dinge darüber: http://ayende.com/blog/3979/nhibernate-futures Beispiel zeigt, wie wir Abfrage ausführen und Ergebnisse Anzahl dieser Abfrage in einer Runde in die Datenbank erhalten können.

Und hier ist eine gute Antwort, die ähnlich klingt, was Sie erreichen wollen: nhibernate 2.0 Efficient Data Paging DataList Control and ObjectDataSource, in dem sie die Ergebnisseite UND Anzahl der Datensätze in einem Umlauf in die Datenbank zählen.

Auch bezweifle ich, dass es möglich ist, pure @@rowcount Wert mit NH ohne Änderung der SQL-Abfrage zu lesen, da @@rowcount Datenbank spezifische Sache ist.

Meine Annahme wäre, dass für Ihren Fall ist es nicht möglich zu vermeiden GetSql from criteria Lösung, es sei denn, Sie vereinfachen Ihre Abfrage oder Ansatz. Vielleicht lohnt es sich auch, dies zu versuchen.

Wenn Sie einen größeren Teil Ihres Codes posten können, wird wahrscheinlich jemand in der Lage sein, dies herauszufinden.

+0

Dies funktioniert nur für nicht komplexe Abfragen, das Problem ist, dass ich Abfragen mit Kriterien erstellt haben, die Gruppe durch Projektionen erhalten haben. Wenn Sie einen der Helfer verwenden oder alle Beispiele im Netz mögen, ist die SQL-Abfrage einfach falsch. –

0

nicht ganz sicher, was Sie wollen, aber so etwas wie dies funktionieren soll (wenn ich Ihre Frage richtig zu verstehen):

var subQuery = DetachedCriteria.For<SomeClass>() 
    .Where(... add your conditions here ...); 

var count = Session.CreateCriteria<SomeClass>() 
    .Where(Property.ForName("Col1").In(
     CriteriaTransformer.Clone(subQuery).SetProjection(Projections.Property("Col1")) 
    .SetProjection(Projections.Count()) 
    .FutureValue<int>(); 

var results = subQuery.GetExecutableCriteria(Session) 
      .SetProjection(Projections.GroupProperty("Col1"), "col1"), 
          Projections.CountDistinct("Col2"), "Count") 
      ).List<object[]>(); 
+0

Es ist etwas, was ich auch vorgeschlagen habe, aber siehe Kommentar unten meine Antwort. –

0

nur ein bisschen über den Tellerrand hinaus zu denken und die Abfrage Komplexität von NHiberate entfernen. Sie können eine Sicht für die Abfrage in der Datenbank erstellen und dann eine Zuordnung für die Sicht vornehmen.

0

Ich habe dieses Problem in der Java-Version (Hibernate) behoben. Das Problem ist, dass die RowProjection Funktion ist etwas wie:

count(*) 

Das ist eine Aggregatfunktion: Wenn Sie also eine ‚Gruppe von‘ Eigentum Ihr Ergebnis ist eine Liste der gruppierten Zeile und für jede Zeile erstellen müssen Sie die Gesamtzählung der Gruppe

Für mich mit Oracle-Datenbank, um es i funktioniert haben eine benutzerdefinierte Projektion erstellen, die anstelle der Funktion count erstellen (*), die Funktion ist

count(count(*)) 

und die Eigenschaft in der Gruppe Klausel wird nicht in die Anweisung select ... from geschrieben.Zu tun, dass es nicht so einfach, das Problem ist, dass Sie alle Stapel zu schaffen, haben das Recht, sql so, mit der Java-Version zu erstellen habe ich 2 Klasse subclasse: SimpleProjection ProjectionList

Danach meine Abfrage generiert als:

select count(*), col1, col2 from table1 group by col1, col2 

werden

select count(count(*)) from table1 group by col1, col2 

und das Ergebnis sind die Gesamtreihe von

gegebenen
select col1, col2 from table1 group by col1, col2 

(verwendbar mit Paginierung System)

poste ich hier die Java-Version der Klassen, wenn nützlich sind für Sie da:

public class CustomProjectionList extends ProjectionList { 

    private static final long serialVersionUID = 5762155180392132152L; 


    @Override 
    public ProjectionList create() { 
     return new CustomProjectionList(); 
    } 

    public static ProjectionList getNewCustomProjectionList() { 
     return new CustomProjectionList(); 
    } 

    @Override 
    public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException { 
     StringBuffer buf = new StringBuffer(); 
     for (int i = 0; i < getLength(); i++) { 
      Projection proj = getProjection(i); 
      String sqlString = proj.toSqlString(criteria, loc, criteriaQuery); 
      buf.append(sqlString); 
      loc += getColumnAliases(loc, criteria, criteriaQuery, proj).length; 
      if (i < (getLength() - 1) && sqlString != null && sqlString.length() > 0) 
       buf.append(", "); 
     } 
     return buf.toString(); 
    } 

    private static String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) { 
     return projection instanceof EnhancedProjection ? 
       ((EnhancedProjection) projection).getColumnAliases(loc, criteria, criteriaQuery) : 
       projection.getColumnAliases(loc); 
    } 


} 

public class CustomPropertyProjection extends SimpleProjection { 


    private static final long serialVersionUID = -5206671448535977079L; 

    private String propertyName; 
    private boolean grouped; 


    @Override 
    public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) { 
     return new String[0]; 
    } 

    @Override 
    public String[] getColumnAliases(int loc) { 
     return new String[0]; 
    } 

    @Override 
    public int getColumnCount(Criteria criteria, CriteriaQuery criteriaQuery) { 
     return 0; 
    } 


    @Override 
    public String[] getAliases() { 
     return new String[0]; 
    } 

    public CustomPropertyProjection(String prop, boolean grouped) { 
     this.propertyName = prop; 
     this.grouped = grouped; 
    } 

    protected CustomPropertyProjection(String prop) { 
     this(prop, false); 
    } 

    public String getPropertyName() { 
     return propertyName; 
    } 

    public String toString() { 
     return propertyName; 
    } 

    public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
    throws HibernateException { 
     return new Type[0]; 
    } 

    public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) 
    throws HibernateException { 

     return ""; 
    } 

    public boolean isGrouped() { 
     return grouped; 
    } 

    public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) 
    throws HibernateException { 
     if (!grouped) { 
      return super.toGroupSqlString(criteria, criteriaQuery); 
     } 
     else { 
      return StringHelper.join(", ", criteriaQuery.getColumns(propertyName, criteria)); 
     } 
    } 

} 

public class CustomRowCountProjection extends SimpleProjection { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = -7886296860233977609L; 


    @SuppressWarnings("rawtypes") 
    private static List ARGS = java.util.Collections.singletonList("*"); 

    public CustomRowCountProjection() { 
     super(); 
    } 


    public String toString() { 
     return "count(count(*))"; 
    } 

    public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { 
     return new Type[] { 
       getFunction(criteriaQuery).getReturnType(null, criteriaQuery.getFactory()) 
     }; 
    } 

    public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException { 
     SQLFunction countSql = getFunction(criteriaQuery); 
     String sqlString = countSql.toString() + "(" + countSql.render(null, ARGS, criteriaQuery.getFactory()) + ") as y" + position + '_'; 
     return sqlString; 
    } 

    protected SQLFunction getFunction(CriteriaQuery criteriaQuery) { 
     SQLFunction function = criteriaQuery.getFactory() 
       .getSqlFunctionRegistry() 
       .findSQLFunction("count"); 
     if (function == null) { 
      throw new HibernateException("Unable to locate count function mapping"); 
     } 
     return function; 
    } 
} 

Hope this Hilfe.