2012-10-18 16 views
7

में लिपटे सामान्य रूप से उपयोग की जाने वाली स्थिति के साथ अज़ूर टेबल स्टोरेज रेंज क्वेरी मेरे पास एक सामान्य अवसर है जहां मैं सभी इकाइयों को प्राप्त करने के लिए एक क्वेरी बनाता हूं जहां विभाजनकी स्थिर है लेकिन पंक्तिकुछ एक अक्षीय सीमा के भीतर होना चाहिए (उदाहरण के लिए केवल पंक्तियां जो शुरू होती हैं कुछ उपसर्ग के साथ):विधि

//query to get all entities in partition "KnownPartition" where RowKey starts with "Prefix_" 
CloudTableQuery<MyEntity> query = 
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName) 
    where e.PartitionKey == "KnownPartition" 
      && e.RowKey.CompareTo("Prefix_") > 0 
      && e.RowKey.CompareTo("Prefix`") <= 0 // ` is '_' + 1 
    select e).AsTableServiceQuery(); 

मैं compareTo का उपयोग करना चाहिए क्योंकि इस तरह StartsWith के रूप में स्ट्रिंग कार्यों क्वेरी इस तरह का में समर्थित नहीं हैं। यह काम करता है, लेकिन स्थिति को पढ़ने और दोहराने के लिए मुश्किल है।

public static Boolean HasPrefix(this String rowKey, String prefix) 
{ 
    return rowKey.CompareTo(prefix + '_') > 0 && rowKey.CompareTo(prefix + '`') <= 0; 
} 

CloudTableQuery<MyEntity> query = 
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName) 
    where e.PartitionKey == "KnownPartition" && e.RowKey.HasPrefix("Prefix") 
    select e).AsTableServiceQuery(); 

लेकिन जब मैं इस चलाने के लिए, मैं से एक अपवाद मिल: तो बजाय इस मुश्किल से पढ़ा शर्त के साथ प्रश्नों का एक बहुत लिखने की, मैं नहीं बल्कि एक समारोह जो "inlined" यह करना चाहते हैं मेरे फ़ंक्शन के बारे में Azure समर्थित नहीं है। क्या इसे लिखने का कोई तरीका है ताकि यह समर्थित हो? आखिरकार, मैं काम करने वाली क्वेरी के समान सटीक स्थिति का उपयोग कर रहा हूं, बस एक फ़ंक्शन में लपेटा गया है ...

उत्तर

10

यदि आप किसी फ़ंक्शन में स्थिति को तोड़ते हैं, तो फ़ंक्शन को अभिव्यक्ति वृक्ष वापस करने की आवश्यकता होती है एक बुलियन मूल्य। मैं अगर LINQ क्वेरी सिंटैक्स इस का समर्थन करेंगे पता नहीं है, लेकिन आप विधि वाक्य रचना के साथ यह कर सकते हैं इस प्रकार है:

public static Expression<Func<MyEntity, bool>> HasPrefix(String prefix) 
{ 
    return e => e.RowKey.CompareTo(prefix + '_') > 0 && e.RowKey.CompareTo(prefix + '`') <= 0; 
} 

CloudTableQuery<MyEntity> query = 
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName) 
    where e.PartitionKey == "KnownPartition" 
    select e) 
    .Where(HasPrefix("Prefix")) 
    .AsTableServiceQuery(); 
+0

बहुत अच्छा, यह काम करता है। धन्यवाद। मुझे लगता है कि हम पूरी अभिव्यक्ति को लिनक क्वेरी सिंटैक्स की बजाय एक विधि श्रृंखला के रूप में लिख सकते हैं जो स्थिर होने के लिए है। –

+0

ओह, वैसे, मुझे उम्मीद है कि इसका परिणाम पूर्ण स्कैन नहीं होगा ... जैसा कि, वास्तव में एज़ूर से स्थानांतरित इकाइयों को पहले से ही उपसर्ग की स्थिति के लिए चेक किया गया है, है ना? –

+1

परिणामस्वरूप एज़ूर स्टोरेज अनुरोध यूआरआई है: https://foo.table.core.windows.net/tablename()?$filter=((पार्टिशनकी ईक 'ज्ञात पार्टिशन') और (रोकी gt 'Prefix_')) और (रोकी ले 'उपसर्ग% 60')। तो केवल सभी पंक्तियों को पूरा करने वाली पंक्तियां वापस कर दी जाएंगी। इसके अलावा, क्योंकि क्वेरी विभाजन कुंजी और पंक्ति कुंजी की एक श्रृंखला निर्दिष्ट करती है, इसलिए बैक एंड पर एक पूर्ण तालिका स्कैन की आवश्यकता नहीं होनी चाहिए। – Kevin

17

यहाँ केविन के जवाब का सामान्यीकरण है। यह वही काम करता है, लेकिन मूल प्रश्न में पूछे जाने वाले विशिष्ट मामले के बजाय किसी भी उपसर्ग स्ट्रिंग के लिए काम करता है।

public static Expression<Func<MyEntity, bool>> HasPrefix(String prefix) 
{ 
    char lastChar = prefix[prefix.Length - 1]; 
    char nextLastChar = (char)((int)lastChar + 1); 
    string nextPrefix = prefix.Substring(0, prefix.Length - 1) + nextLastChar; 

    return e => e.RowKey.CompareTo(prefix) >= 0 && e.RowKey.CompareTo(nextPrefix) < 0; 
} 
+0

सामान्यीकृत उत्तर प्रदान करने के लिए धन्यवाद! एमएस को इस बिट को linq क्वेरी प्रोसेसर में शामिल करना चाहिए था! –

संबंधित मुद्दे