【发布时间】:2015-11-29 18:48:55
【问题描述】:
我想在从数据库填充的 DataTable 上动态构建以下 Select 语句中使用的 linq 表达式:
IQueryable iq = myDataTable
.AsEnumerable()
.AsQueryable()
.Select(
d => new {
Field1 = d.Field<int>(37),
Field2 = d.Field<string>(0),
Field3 = d.Field<DateTime>(1)
}
);
这些字段在运行前是未知的。我会在运行时。
有什么方法可以实现吗?
[更新]
我开始写下面的代码:
Type type = typeof(DataRow);
MethodInfo mi1 = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(int) });
mi1 = mi1.MakeGenericMethod(type);
List<Expression> list1 = new List<Expression>();
ParameterExpression datarow1 = Expression.Parameter(type, "datarow");
ConstantExpression constant1 = Expression.Constant(37, typeof(int));
list1.Add(datarow1);
list1.Add(constant1);
ReadOnlyCollection<Expression> collection1 = new ReadOnlyCollection<Expression>(list1);
MethodCallExpression right1 = Expression.Call(null, mi1, datarow1, constant1);
Expression left1 = Expression.Parameter(type, "Field1");
var expression1 = Expression.Assign(left1, right1);
MethodInfo mi2 = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(int) });
mi2 = mi2.MakeGenericMethod(type);
List<Expression> list2 = new List<Expression>();
ParameterExpression datarow2 = Expression.Parameter(type, "datarow");
ConstantExpression constant2 = Expression.Constant(0, typeof(int));
list2.Add(datarow2);
list2.Add(constant2);
ReadOnlyCollection<Expression> collection2 = new ReadOnlyCollection<Expression>(list2);
MethodCallExpression right2 = Expression.Call(null, mi2, datarow2, constant2);
Expression left2 = Expression.Parameter(type, "Field2");
var expression2 = Expression.Assign(left2, right2);
List<Expression> bindings = new List<Expression>();
bindings.Add(expression1);
bindings.Add(expression2);
var newInit = Expression.New(typeof(object));
var init = Expression.NewArrayInit(type, bindings);
var dr = Expression.Parameter(type, "dr");
var linq = Expression.Lambda<Func<DataRow, DataRow>>(init, dr);
它可以编译,但是有几个问题:
- 表达式1 是
(Field1 = datarow.Field(0))而不是Field1 = datarow.Field<int>(0) - 与表达式 2 相同
- 它抛出一个运行时异常:
'System.Data.DataRow[]' cannot be used for return type 'System.Data.DataRow'在线var linq = Expression.Lambda...
你能帮忙吗?
@乔治 我想我不需要 Type 字典,因为我有一组预定义的类型。
【问题讨论】:
-
查看动态 linq 库,除非您想开始构建表达式树
-
首先,调用“AsEnumerable()”后跟“AsQueryable”似乎很糟糕。从您的示例中,您的数据在内存中。一般来说,如果你的数据在内存中,你不需要调用 AsQueryable,如果你的数据在 db 中(所以 myDataTable 实际上是一个对象集),你不需要先调用 AsEnumerable。
-
构建动态查询(在字符串中)然后运行它
-
@Goerge Lica:我需要一个 IQueryable 结果。将 DataTable 转换为 IQueryable 的唯一方法是依次调用 .AsEnumerable( ).AsQueryable( )。 DataTable 不直接实现 AsQueryable()。