Question

I am trying to write something that will allow custom expressions be stored in strings to be evaluated against various data. After several failed attempts I was able to find something successful, but it doesn't lend itself to the intent.

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

How can I accomplish this? All roads seems to lead back to this article: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx But I do not see the answer to what I am trying to do as he is using strongly typed data.

Thanks!

Était-ce utile?

La solution

If you want use DynamicLINQ you need change your code.

1) this expression

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

is same

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

so DynamicLinq try find property Age for DataRow and since DataRow class don't have this property you get error No property or field 'Age' exists in type 'DataRow'


2) in this expression

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

DynamicLinq try find property or method Field, but it is extension method in DataRowExtensions, so you also get error No property or field 'Field' exists in type 'DataRow'


3) this expression is same as first with using parameters

var result3 = test.Where("Age=@0", 32);  // Error received:  {"No property or field 'Age' exists in type 'DataRow'"}

Next two expression equivalent, becuase when DynamicLinq parse expression, it parse both = and == as 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'"}

if you see about DataRow.Item property you can see that it return Object, so for checking equals you need cast object result to int something like this

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

also, possibly, in this case you can help paramtrize form like this

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

at last here

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

after parsing expression DynamicLinq get lambda that don't return Boolean, so you get error Expression of type 'Boolean' expected

Autres conseils

This should get you what you're looking for. Put in your null checking in case there are no columns that match the supplied string name etc...

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top