【问题标题】:Using LINQ to evaluate expressions from a string against a datatable使用 LINQ 根据数据表计算字符串中的表达式
【发布时间】:2014-05-25 23:58:34
【问题描述】:

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

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 但我看不到我正在尝试做的事情的答案,因为他正在使用强类型数据。

谢谢!

【问题讨论】:

  • 不是linq,而是DataTable.Select() 方法有用吗?
  • 我从未尝试过将 Dynamic Linq 与 DataTable 一起使用。我想知道您是否会考虑不使用 DataTable 的选项?
  • 这会起作用:dt.Select("Age=32");这也可以: dt.AsEnumerable().Where(a => a["Name"].Equals("John"));
  • DaveParsons 和 Arie 对,但现在我有点困惑。为什么 Select("Age=32") 有效而 Where("Age=32") 无效?我只使用了 Where to begin with,因为我认为它是用于过滤的?
  • @jrandomuser 它们是查询DataTable 的完全不相关的方法。一个特定于DataTable,并且已经存在了更长的时间。另一个是 LINQ,它不仅特定于数据表,而且具有非常不同的查询方法。

标签: c# linq dynamic-linq


【解决方案1】:

如果您想使用 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 类没有此属性,您会收到错误 No property or field 'Age'存在于“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' 中不存在属性或字段'Field'


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");

也可能,在这种情况下,您可以像这样帮助对表单进行参数化

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,所以你得到错误 Expression of type 'Boolean' expected

【讨论】:

    【解决方案2】:

    这应该可以为您提供所需的内容。如果没有与提供的字符串名称匹配的列等,请进行 null 检查...

    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      • 1970-01-01
      相关资源
      最近更新 更多