2015-05-04 110 views
-2

我有一個DataClassesDataContext包含一組表,我試圖做lambda expression動態過濾使用只有表的名稱和字段的名稱。基本上我想爲每個表找到一個具有特定ID的行是否已經存在。SingleOr的動態lambda表達式默認

如果我知道時間提前的表,我會用:

if (dataClassesDataContext.MYTABLEXs.SingleOrDefault(m => m.MYTABLEX_ID == MyId)) 
    DoExists(); 

但正如我得到的表名MYTABLEX和MYTABLEY(和字段名MYTABLEX_ID和MYTABLEY_ID)作爲對飛弦,我試圖在運行時構建上述過濾器。

我可以訪問使用動態表:

Type tableType = Type.GetType(incommingtableName); // incommingtableName being looped over MYTABLEX, MYTABLEY , ... 
var dbTable = dataClassesDataContext.GetTable(tableType); 

但後來我卡住了。我如何建立一個表達如下的lambda表達式:

if (dbTable.SingleOrDefault(m => m.incommingtableName_id == MyId)) 
    DoExists(); 

任何想法?

+0

您可以用[表達式](HTTPS構建它們: //msdn.microsoft.com/en-us/library/system.linq.expressions.expression%28v=vs.110%29.aspx)類,允許您在運行時動態構建表達式 –

回答

1

您可以在運行時構建表達式。而且您還需要有通用版本的SingleOrDefault方法。下面是例子:

Type tableType = typeof (incommingtableName); // table type 
string idPropertyName = "ID"; // id property name 
int myId = 42; // value for searching 

// here we are building lambda expression dynamically. It will be like m => m.ID = 42; 
ParameterExpression param = Expression.Parameter(tableType, "m"); 
MemberExpression idProperty = Expression.PropertyOrField(param, idPropertyName); 
ConstantExpression constValue = Expression.Constant(myId); 

BinaryExpression body = Expression.Equal(idProperty, constValue); 

var lambda = Expression.Lambda(body, param); 


// then we would need to get generic method. As SingleOrDefault is generic method, we are searching for it, 
// and then construct it based on tableType parameter 

// in my example i've used CodeFirst context, but it shouldn't matter 
SupplyDepot.DAL.SupplyDepotContext context = new SupplyDepotContext(); 
var dbTable = context.Set(tableType); 


// here we are getting SingleOrDefault<T>(Expression) method and making it as SingleOrDefault<tableType>(Expression) 
var genericSingleOrDefaultMethod = 
    typeof (Queryable).GetMethods().First(m => m.Name == "SingleOrDefault" && m.GetParameters().Length == 2); 
var specificSingleOrDefault = genericSingleOrDefaultMethod.MakeGenericMethod(tableType); 

// and finally we are exexuting it with constructed lambda 
var result = specificSingleOrDefault.Invoke(null, new object[] { dbTable, lambda }); 

至於可能的優化構建拉姆達可以被緩存,因此我們不會每次都需要構建它,但它應該工作一樣

+0

感謝您的代碼 – Yahia