2015-07-10 52 views
4

我正在嘗試使用Linq表達式爲IQueryable數據源創建動態where子句。我無法使TryParse函數在其中一個表達式中工作。這裏是我想要做的事:無法獲得double.TryParse在Linq表達式樹中工作

IQueryable<trial_global> globalTrials = _trialsRepository.GlobalDataFiltered(filterId).AsQueryable(); 

BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Static; 
MethodInfo tryParseMethod = typeof(double).GetMethod("TryParse", bindingFlags, null, new Type[] { typeof(string), typeof(double).MakeByRefType() }, null); 
Expression tempN = Expression.Parameter(typeof(double), "tempN"); 
Expression left = Expression.Call(tryParseMethod, new[] { metricReference, tempN }); 

Expression right = Expression.Constant(true); 
Expression predicateBody = Expression.Equal(left, right); 

MethodCallExpression whereCallExpression = Expression.Call(
          typeof(Queryable), 
          "Where", 
          new Type[] { globalTrials.ElementType }, 
          globalTrials.Expression, 
          Expression.Lambda<Func<trial_global, bool>>(predicateBody, new ParameterExpression[] { pe }) 
          ); 

var results = globalTrials.Provider.CreateQuery<trial_global>(whereCallExpression); 

一切工作正常,直到results被分配在那裏我得到以下錯誤:

variable 'tempN' of type 'System.Double' referenced from scope '', but it is not defined 

缺少什麼我在這裏?我懷疑它與double.TryParse函數中的第二個參數是out參數有關。

UPDATE:

我解決這個問題通過了由公式創建一個靜態的功能它執行的TryParse和調用這個靜態函數:

public static bool IsStringNumeric(string checkStr) 
{ 
    double num = 0; 
    return double.TryParse(checkStr, out num); 
} 

public IQueryable<trial_global> GetTrials(IQueryable<trial_global> globalTrials, Metric metric) 
{ 
    ParameterExpression pe = Expression.Parameter(typeof(trial_global), "trial_global"); 
    MemberExpression metricReference = Expression.Property(pe, metric.metric_name); 

    Expression predicateBody = Expression.Call(typeof(GlobalTrialsRepository).GetMethod("IsStringNumeric", new Type[] { typeof(string) }), metricReference); 

    MethodCallExpression whereCallExpression = Expression.Call(
       typeof(Queryable), 
       "Where", 
       new Type[] { globalTrials.ElementType }, 
       globalTrials.Expression, 
       Expression.Lambda<Func<trial_global, bool>>(predicateBody, new ParameterExpression[] { pe }) 
       ); 

    return globalTrials.Provider.CreateQuery<trial_global>(whereCallExpression); 
} 

是這種方法好不好?有沒有人看到這樣做的缺點?

+5

如果您要將謂詞寫入lambda表達式,它會是什麼樣子? – MarcinJuraszek

+0

沒有必要生成'x == true'。 – SLaks

+5

另外,很少LINQ提供者會處理'TryParse()'。 – SLaks

回答

0

Tryparse用於檢查參數。使用tryparse創建一個擴展方法,然後調用linq的擴展方法

+1

他可以創建表達式,但它不會與幾乎任何提供者一起運行。 – usr

+0

什麼提供商可以理解double.TryParse呢? – MBoros

+0

對不起,雖然他想要一個函數來驗證一個正常的linq語句 – Juan

0

Linq查詢被推遲到調用ToXXXX()爲止。因此,您可以將Where語句定義爲Linq方法鏈,然後調用.ToList或任何值來獲取該值。

+0

如果我理解你正確的你說我應該做一些像'var res = _datasource.Where(a => a.Col1 =='xyz')。 ToList()'我不能這樣做的原因是我想要查詢的列('Col1')事先不知道。它會動態地發生,因此需要創建動態表達式。 – user2056023