SingleOrDefault 的动态 lambda 表达式
Dynamic lambda expression for SingleOrDefault
我有一个包含一组 table 的 DataClassesDataContext
,我正在尝试仅使用 table 的名称动态地进行 lambda expression
过滤,并且字段的名称。基本上我想为每个 table 查找是否已经存在具有特定 ID 的行。
如果我提前知道 table,我会使用 :
if (dataClassesDataContext.MYTABLEXs.SingleOrDefault(m => m.MYTABLEX_ID == MyId))
DoExists();
但是当我将 table 的名称 MYTABLEX 和 MYTABLEY(以及字段名称 MYTABLEX_ID 和 MYTABLEY_ID)动态地作为字符串时,我正在尝试构建上述过滤器在运行时。
我可以使用 :
动态访问 table
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();
有什么想法吗?
您可以在运行时构建表达式。而且您还需要具有 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 });
尽可能优化构造的 lambda 可以被缓存,所以我们不需要每次都构建它,但它应该工作相同
我有一个包含一组 table 的 DataClassesDataContext
,我正在尝试仅使用 table 的名称动态地进行 lambda expression
过滤,并且字段的名称。基本上我想为每个 table 查找是否已经存在具有特定 ID 的行。
如果我提前知道 table,我会使用 :
if (dataClassesDataContext.MYTABLEXs.SingleOrDefault(m => m.MYTABLEX_ID == MyId))
DoExists();
但是当我将 table 的名称 MYTABLEX 和 MYTABLEY(以及字段名称 MYTABLEX_ID 和 MYTABLEY_ID)动态地作为字符串时,我正在尝试构建上述过滤器在运行时。
我可以使用 :
动态访问 tableType 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();
有什么想法吗?
您可以在运行时构建表达式。而且您还需要具有 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 });
尽可能优化构造的 lambda 可以被缓存,所以我们不需要每次都构建它,但它应该工作相同