2011-05-12 58 views
1

我試圖做一些看起來很簡單的事情,但是當我想讓這種動態變得更加動態時,我遇到了很多困難。TableServiceContext和動態查詢

Expression<Func<TableServiceEntity, bool>> predicate = (e) => e.PartitionKey == "model" && (e.RowKey == "home" || e.RowKey == "shared"); 

context.CreateQuery<TableServiceEntity>(tableName).Where(predicate); 

我想傳遞一個rowKey數組,而不必硬編碼謂詞。

當我嘗試構建表達式樹時,我收到一個不受支持的異常,我認爲它不支持作爲表達式樹的一部分進行調用。

有人知道如何構建和表達樹完全一樣的謂詞,以避免不受支持的異常?

通過提前謝謝

回答

2

所以,你可以用這樣的動態生成查詢(從PhluffyFotos樣本獲取):

 Expression<Func<PhotoTagRow, bool>> search = null; 
     foreach (var tag in tags) 
     { 
      var id = tag.Trim().ToLowerInvariant(); 

      if (String.IsNullOrEmpty(id)) 
      { 
       continue; 
      } 

      Expression<Func<PhotoTagRow, bool>> addendum = t => t.PartitionKey == id; 

      if (search == null) 
      { 
       search = addendum; 
      } 
      else 
      { 
       search = Expression.Lambda<Func<PhotoTagRow, bool>>(Expression.OrElse(search.Body, addendum.Body), search.Parameters); 
      } 
     } 

現在,一旦你擁有了「搜索」你可以把它作爲Where子句中的謂詞。

但是,我想說服你不要這樣做。我正在回答你的問題,但告訴你做一個多個'|'是一個壞主意。 OR表中的OR子句存儲。原因在於,至少在今天,這些查詢無法進行優化,導致全表掃描。對於任何不重要的數據量來說,性能將會非常可怕。此外,如果您像這樣動態構建謂詞,則會冒着吹響URL限制的風險(記住這一點)。

PhluffyFotos中的這段代碼展示了它是如何的,但它實際上是一種不好的做法(我知道,我寫了它)。它確實應該被優化以並行運行每個OR子句。這就是你應該如何去做的。 AND子句是可以的,但OR子句應該並行化(使用PLINQ或TPL),你應該彙總結果。它會更快。

HTH。

+0

您好HTH, 感謝您的意見,您對Or子句不優化的評論對我來說是無價的!我會看看PLINQ,並改變我的執行方式。 我設法用下面的其他方式做表達式。 再次感謝你很有價值 – 2011-05-14 10:30:02

0

這裏是我的解決方案,請閱讀HTH的回答,他指出這不是最佳做法。

var parameter = Expression.Parameter(typeof(TableServiceEntity), "e"); 

var getPartitionKey = typeof(TableServiceEntity).GetProperty("PartitionKey").GetGetMethod(); 
var getRowKey = typeof(TableServiceEntity).GetProperty("RowKey").GetGetMethod(); 

var getPartition = Expression.Property(parameter, getPartitionKey); 
var getRow = Expression.Property(parameter, getRowKey); 

var constPartition = Expression.Constant("model", typeof(string)); 
var constRow1 = Expression.Constant("home", typeof(string)); 
var constRow2 = Expression.Constant("shared", typeof(string)); 

var equalPartition = Expression.Equal(getPartition, constPartition); 
var equalRow1 = Expression.Equal(getRow, constRow1); 
var equalRow2 = Expression.Equal(getRow, constRow2); 

var and = Expression.AndAlso(equalPartition, Expression.OrElse(equalRow1, equalRow2)); 

return Expression.Lambda<Func<TableServiceEntity, bool>>(and, parameter); 
+1

LOL。 HTH是「希望有助於」的簡寫。我的屏幕名稱是'dunnry'。 :) – dunnry 2011-05-16 18:57:35

+0

大聲笑確實:),我會記得一個:) – 2011-06-22 19:17:08

1

我相信HTH對這種查詢進行全表掃描所說的話,從我讀過的文檔中是不正確的。 Azure將執行PARTITION掃描,而不是TABLE掃描,這在性能上有很大差異。