使用LINQ从字符串中针对数据表计算表达式

时间:2014-05-09 13:50:08

标签: c# linq dynamic-linq

我正在尝试写一些允许自定义表达式存储在字符串中的内容,以便针对各种数据进行评估。经过几次尝试失败后,我找到了一些成功的东西,但它并不适合这个意图。

DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Name", typeof(string)));
dt.Columns.Add(new DataColumn("Age", typeof(int)));

dt.Rows.Add(new object[] { "John", 32 });

var test = dt.AsEnumerable().AsQueryable();

// An example of an expression to test
string expression = "Age = 32";

// Failed Attempts
//var result1 = test.Where(expression); // Error received:  {"No property or field 'Age' exists in type 'DataRow'"}
//var result2 = test.Where("it.Field<object>(\"Age\") == 32");  // Error received:  {"No property or field 'Field' exists in type 'DataRow'"}
//var result3 = test.Where("Age=@0", 32);  // Error received:  {"No property or field 'Age' exists in type 'DataRow'"}
//var result4 = test.Where("it[\"Age\"] == 127"); // Error received:  {"Operator '==' incompatible with operand types 'Object' and 'Int32'"}
//var result5 = test.Where("it[\"Age\"] = 127");  // Error received:  {"Operator '=' incompatible with operand types 'Object' and 'Int32'"}
//var result6 = test.Where("it[\"Age\"] as Age  = 127");  // Error received:  {"Expression of type 'Boolean' expected"}

// Successful but at this point its not really a dynamic linq expression
var result = test.Where(it => it.Field<int>("Age") == 32);

我怎样才能做到这一点?所有的道路似乎都可以回到这篇文章:http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx但我没有看到我正在尝试做的事情的答案,因为他正在使用强类型数据。

谢谢!

2 个答案:

答案 0 :(得分:2)

如果您想使用DynamicLINQ,则需要更改代码。

1)这个表达

// Failed Attempts
string expression = "Age = 32";
var result1 = test.Where(expression); // Error received:  {"No property or field 'Age' exists in type 'DataRow'"}

是相同的

// Failed Attempts
var result1 = test.Where("Age = 32"); // Error received:  {"No property or field 'Age' exists in type 'DataRow'"}

所以DynamicLinq尝试为 DataRow 查找属性Age,并且由于 DataRow 类没有此属性,您会收到错误无属性或字段'年龄'存在于'DataRow'类型


2)在这个表达式中

var result2 = test.Where("it.Field<object>(\"Age\") == 32");  // Error received:  {"No property or field 'Field' exists in type 'DataRow'"}

DynamicLinq尝试查找属性或方法Field,但它是DataRowExtensions中的扩展方法,因此您也会收到错误“DataRow”类型中没有属性或字段“字段”


3)此表达式与使用参数

的第一个表达式相同
var result3 = test.Where("Age=@0", 32);  // Error received:  {"No property or field 'Age' exists in type 'DataRow'"}

接下来两个表达式等价,因为当DynamicLinq解析表达式时,它将===解析为Equals

var result4 = test.Where("it[\"Age\"] == 127"); // Error received:  {"Operator '==' incompatible with operand types 'Object' and 'Int32'"}
var result5 = test.Where("it[\"Age\"] = 127");  // Error received:  {"Operator '=' incompatible with operand types 'Object' and 'Int32'"}

如果你看到DataRow.Item属性,你可以看到它返回Object,所以为了检查等于你需要将对象结果转换为int这样的东西

var result4 = test.Where("Convert.ToInt32(it[\"Age\"]) == 127");

也可能,在这种情况下,你可以像这样帮助paramtrize形式

var result4 = test.Where("it[\"Age\"] == @0",127);

最后在这里

var result6 = test.Where("it[\"Age\"] as Age  = 127");  // Error received:  {"Expression of type 'Boolean' expected"}

解析表达式后,DynamicLinq获取不返回Boolean的lambda,因此会出现错误预期类型为'Boolean'的表达式

答案 1 :(得分:-1)

这应该可以帮到你找到你想要的东西。如果没有与提供的字符串名称匹配的列等等,请进行空检查。

int age = 32;
string column = "Age";

DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Name", typeof(string)));
dt.Columns.Add(new DataColumn("Age", typeof(int)));

dt.Rows.Add(new object[] { "John", 32 });

var result = dt.AsEnumerable().Where(r => Convert.ToInt32(r[column]) == age);