2012-04-11 17 views
7

द्वारा समूह है, मुझे मानदंड क्वेरी से पंक्तियों की गिनती प्राप्त करने की आवश्यकता है और मानदंड अनुमानों के अनुसार समूह प्राप्त करने की आवश्यकता है। (काम करने के लिए पेजिंग प्राप्त करने के लिए आवश्यक)एनएचबेर्नेट, पंक्तियों को प्राप्त करें जब मानदंड

उदा।

projectionList.Add(Projections.GroupProperty("Col1"), "col1") 
       .Add(Projections.CountDistinct("Col2"), "Count"); 

मैं, CreateSQL बचने की जरूरत है के बाद से मैं मापदंड का एक बहुत .. है और प्रतिबंध आदि जटिल हैं।

क्या आप एक सबक्रिटिरिया (अलग) और फिर select count(*) from .. कर सकते हैं? कैसे पता नहीं लगा सकता है?

संपादित करें: मैंने एसक्यूएल को मानदंडों से प्राप्त करके हल किया और फिर इसे संशोधित किया ताकि यह अब काम कर सके! GetSql from criteria

+0

मैं वही काम करना चाहता हूं ... लेकिन GetSQL समाधान से बचें। –

+0

हां, यह समाधान दर्दनाक था, मानदंडों से एसक्यूएल प्राप्त करने के लिए आवश्यक है लेकिन आप मानदंडों से पैरामीटर प्रकार या मान प्राप्त नहीं कर सकते हैं (एक आसान तरीके से) ताकि हमें मूल्यों को संग्रहीत करने के लिए एक और संग्रह की आवश्यकता हो, और उन्हें सही क्रम में होना आदि .. –

+0

आपने वास्तव में एसक्यूएल में क्या रखा? मुझे अभी भी समझ में नहीं आता कि आपको क्या परिणाम चाहिए। –

उत्तर

0

मुझे लगता है कि यह एनएच मल्टी क्वेरीज़ का उपयोग करके किया जा सकता है।

यहां कुछ सामान है: http://ayende.com/blog/3979/nhibernate-futures उदाहरण दिखाता है कि हम क्वेरी कैसे चला सकते हैं और डेटाबेस में एक राउंडट्रिप में उस क्वेरी की परिणाम गिनती प्राप्त कर सकते हैं।

और यहां अच्छा जवाब है, जो आप प्राप्त करना चाहते हैं: nhibernate 2.0 Efficient Data Paging DataList Control and ObjectDataSource जिसमें उन्हें परिणाम पृष्ठ मिलता है और कुल रिकॉर्ड डेटाबेस में एक राउंडट्रिप में गिना जाता है।

इसके अलावा, मुझे संदेह है कि एसक्यूएल क्वेरी बदलने के बिना एनएच के साथ शुद्ध @@rowcount मूल्य पढ़ना संभव है, क्योंकि @@rowcount डेटाबेस विशिष्ट चीज़ है।

मेरी धारणा यह होगी कि आपके मामले के लिए GetSql from criteria समाधान से बचना संभव नहीं है, जब तक कि आप अपनी क्वेरी या दृष्टिकोण को सरल नहीं बनाते। शायद यह भी कोशिश करने लायक है।

यदि आप अपने कोड का बड़ा हिस्सा पोस्ट कर सकते हैं, तो शायद कोई इसे समझ पाएगा।

+0

यह केवल गैर-जटिल प्रश्नों के लिए काम करता है, समस्या यह है कि मुझे मानदंडों के साथ बनाए गए प्रश्न मिलते हैं जो अनुमानों के अनुसार समूह प्राप्त करते हैं। जब आप किसी भी सहायक का उपयोग करते हैं, या नेट पर सभी उदाहरणों की तरह करते हैं, तो एसक्यूएल क्वेरी सिर्फ गलत है .. –

0

पूरी तरह से सुनिश्चित करें कि आप क्या चाहते हैं, लेकिन कुछ इस तरह काम करना चाहिए (अगर मैं आपके सवाल का ठीक से समझ) नहीं:

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

यह कुछ भी है जो मैंने प्रस्तावित किया है, लेकिन मेरे उत्तर के नीचे टिप्पणी देखें। –

0

बस बॉक्स के बाहर एक सा लगता है और NHiberate से क्वेरी जटिलता को दूर करने के। आप डेटाबेस में क्वेरी के लिए एक दृश्य बना सकते हैं और फिर दृश्य के लिए मैपिंग कर सकते हैं।

0

मैंने जावा संस्करण (हाइबरनेट) पर इस समस्या का समाधान किया है। समस्या RowProjection समारोह है कि है कुछ की तरह:

count(*) 

एक समग्र समारोह है कि: इसलिए यदि आप संपत्ति 'द्वारा समूह' एक बनाने के अपने परिणाम वर्गीकृत किया पंक्ति की एक सूची है और प्रत्येक पंक्ति के लिए आपके पास समूह की कुल गिनती।

मेरे लिए, Oracle डाटाबेस के साथ, यह काम मैं कि, बजाय समारोह गिनती (*) बनाने के लिए एक कस्टम प्रक्षेपण बनाने है बनाने के लिए, समारोह

count(count(*)) 

और से समूह में संपत्ति है खंड से चयन ... में खंड नहीं लिखा गया है।यह इतना आसान नहीं है, समस्या आप जावा संस्करण के साथ तो सही एसक्यूएल बनाने के लिए, सभी ढेर प्रदान करने के लिए है कि यह है कि ऐसा करने के लिए मैं 2 वर्ग subclasse करना है: कि मेरी क्वेरी उत्पन्न होने के बाद SimpleProjection ProjectionList

के रूप में:

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

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

हो जाते हैं और परिणाम कुल पंक्ति

द्वारा दिए गए हैं

(पृष्ठांकन प्रणाली के साथ प्रयोग करने योग्य)

मैं यहाँ पोस्ट वर्गों के जावा संस्करण, अगर आप के लिए उपयोगी होते हैं:

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; 
    } 
} 

आशा इस मदद करते हैं।