Mike Eghtebas
asked on
dynamic LINQ string... c# part 2
In an attempt to create a dynamic LINQ string, to replace field names with fieldName dynamically set by:
string filedName = lb.ID.Substring(3);
so far I have the following code with 3 errors:
1 'System.Func<System.Data.L inq.Table< Search>,st ring>' is a 'type' but is used like a 'variable' at line 12:
Func<Table<Search>, string> getField = Expression.Lambda < Func<Table<Search>, string>(Expression.Propert y(o, fieldName), o);
3. Argument 1: cannot convert from 'Search' to 'System.Data.Linq.Table<Se arch>' at line 15:
orderby getField(output)
2. Delegate 'System.Func<System.Data.L inq.Table< Search>,st ring>' has some invalid arguments. also at line 15:
orderby getField(output)
FYI: Using F12 on Searches takes me to:
public System.Data.Linq.Table<Search> Searches
So, in my code above I have used Table<Search> as type.
Also, holding cursor on 'Searches' shows me: Table <Search> WSCGSoftwareDataContext.Se arches
string filedName = lb.ID.Substring(3);
so far I have the following code with 3 errors:
1 'System.Func<System.Data.L
Func<Table<Search>, string> getField = Expression.Lambda < Func<Table<Search>, string>(Expression.Propert
3. Argument 1: cannot convert from 'Search' to 'System.Data.Linq.Table<Se
orderby getField(output)
2. Delegate 'System.Func<System.Data.L
orderby getField(output)
private static object GetPropertyValue(object obj, string property)
{
System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(property);
return (string)propertyInfo.GetValue(obj, null);
}
private void LoadListBoxes(ListBox lb)
{
lb.Items.Clear();
string fieldName = lb.ID.Substring(3);
ParameterExpression o = Expression.Parameter(typeof(Table<Search>));
Func<Table<Search>, string> getField = Expression.Lambda < Func<Table<Search>, string>(Expression.Property(o, fieldName), o);
ListItem[] outputs = (from output in wscgsContext.Searches
orderby getField(output)
group output by getField(output) into theGroup
select new ListItem(getField(theGroup.FirstOrDefault())).ToArray());
lb.Items.AddRange(outputs);
FYI: Using F12 on Searches takes me to:
public System.Data.Linq.Table<Search> Searches
So, in my code above I have used Table<Search> as type.
Also, holding cursor on 'Searches' shows me: Table <Search> WSCGSoftwareDataContext.Se
What is a "dynamic LINQ string"?
ASKER
louisfr,
I got the following two errors:
Error 1 'System.Func<Search,string >' is a 'type' but is used like a 'variable' at line 2:
Func<Search, string> getField = Expression.Lambda < Func<Search, string>(Expression.Propert y(o, fieldName), o);
Error 2 'System.Web.UI.WebControls .ListItem' does not contain a definition for 'ToArray' and no extension method 'ToArray' accepting a first argument of type 'System.Web.UI.WebControls .ListItem' could be found (are you missing a using directive or an assembly reference?) at line 7:
select new ListItem(getField(theGroup .FirstOrDe fault())). ToArray()) ;
Ste5an,
The following worked to handle field named City. This is what I started with but it has been evolved the code I have in my original question.
Take this code (which handles specifically field City) and make it work for any field name created by:
string fieldName = lb.ID.Substring(3);
I got the following two errors:
Error 1 'System.Func<Search,string
Func<Search, string> getField = Expression.Lambda < Func<Search, string>(Expression.Propert
Error 2 'System.Web.UI.WebControls
select new ListItem(getField(theGroup
ParameterExpression o = Expression.Parameter(typeof(Search));
Func<Search, string> getField = Expression.Lambda < Func<Search, string>(Expression.Property(o, fieldName), o);
ListItem[] outputs = (from output in wscgsContext.Searches
orderby getField(output)
group output by getField(output) into theGroup
select new ListItem(getField(theGroup.FirstOrDefault())).ToArray());
lb.Items.AddRange(outputs);
-------------------------Ste5an,
The following worked to handle field named City. This is what I started with but it has been evolved the code I have in my original question.
ListItem[] outputs4 = (from output in wscgsContext.Searches
orderby output.City
group output by output.City into theGroup
select new ListItem(theGroup.FirstOrDefault().City)).ToArray();
lb.Items.AddRange(outputs4);
re:> What is a "dynamic LINQ string"?Take this code (which handles specifically field City) and make it work for any field name created by:
string fieldName = lb.ID.Substring(3);
There's a missing > and a call to compile to create the delegate from the expression.
ParameterExpression o = Expression.Parameter(typeof(Search));
Func<Search, string> getField = Expression.Lambda<Func<Search, string>>(Expression.Property(o, fieldName), o).Compile();
ASKER
louisfr,
This fixed one error and revised the second error stating:
Error 1 'System.Web.UI.WebControls .ListItem' does not contain a definition for 'ToArray' and no extension method 'ToArray' accepting a first argument of type 'System.Web.UI.WebControls .ListItem' could be found (are you missing a using directive or an assembly reference?)
at:
select new ListItem(getField(theGroup .FirstOrDe fault())). ToArray()) ;
This fixed one error and revised the second error stating:
Error 1 'System.Web.UI.WebControls
at:
select new ListItem(getField(theGroup
Check the parentheses. There is one too much after ToArray() that should be before it.
select new ListItem(getField(theGroup.FirstOrDefault()))).ToArray();
ASKER
runtime error at the end of this line:
select new ListItem(getField(theGroup .FirstOrDe fault()))) .ToArray() ;
Method 'System.Object DynamicInvoke(System.Objec t[])' has no supported translation to SQL.
select new ListItem(getField(theGroup
Method 'System.Object DynamicInvoke(System.Objec
ASKER
FYI, I am reading this: http://tomasp.net/blog/dynamic-linq-queries.aspx/
That means we can't use delegates. And we cannot use reflection and GetProperty. We have to use expressions without compiling them. Easy for the orderby and group. Let's see...
ParameterExpression o = Expression.Parameter(typeof(Table<Search>));
var getField = Expression.Lambda<Func<Search, string>>(Expression.Property(o, fieldName), o);
ListItem[] outputs = (wscgsContext.Searches
.OrderBy(getField)
.GroupBy(getField)
.Select(theGroup=>theGroup.FirstOrDefault())
.Select(getField)
.Select(field => new ListItem(field))).ToArray();
ASKER
1. I had to add ) in the line below:
.Select(field => new ListItem(field))).ToArray();
2. Runtime error: Instance property 'First_Name' is not defined for type 'System.Data.Linq.Table`1[ Search]' at the end of line.
var getField = Expression.Lambda<Func<Sea rch, string>>(Expression.Proper ty(o, fieldName), o);
.Select(field => new ListItem(field))).ToArray();
2. Runtime error: Instance property 'First_Name' is not defined for type 'System.Data.Linq.Table`1[
var getField = Expression.Lambda<Func<Sea
You tried to use the expression with a field name which isn't in the Search table.
ASKER
louisfr,
Basically, I am looking for a solution that woks. The link I gave you (http://tomasp.net/blog/dynamic-linq-queries.aspx/), seems to suggest this is possible.
I am starting to do its exercises to eventually make this happen. I will post the result here later.
Wish me luck,
Mike
Basically, I am looking for a solution that woks. The link I gave you (http://tomasp.net/blog/dynamic-linq-queries.aspx/), seems to suggest this is possible.
I am starting to do its exercises to eventually make this happen. I will post the result here later.
Wish me luck,
Mike
Is there a "First_Name" property in the "Search" table?
ASKER
Yes, it is the first one.
Dictionary<string, bool> listBoxes = new Dictionary<string, bool>();
listBoxes.Add("First_Name" , true);
listBoxes.Add("Last_Name", true);
listBoxes.Add("Address", true);
listBoxes.Add("City", true);
listBoxes.Add("State", true);
listBoxes.Add("Zip_Code", true);
listBoxes.Add("Phone", true);
listBoxes.Add("Email", true);
listBoxes.Add("Order_Date" , true);
listBoxes.Add("Title", true);
listBoxes.Add("Unit_Price" , true);
listBoxes.Add("Quantity", true);
BTW, any help at https://www.experts-exchange.com/questions/28562832/Store-meta-data-from-dbml-table-in-a-dictionary-variable.html will be also appreciated.
Mike
Dictionary<string, bool> listBoxes = new Dictionary<string, bool>();
listBoxes.Add("First_Name"
listBoxes.Add("Last_Name",
listBoxes.Add("Address", true);
listBoxes.Add("City", true);
listBoxes.Add("State", true);
listBoxes.Add("Zip_Code", true);
listBoxes.Add("Phone", true);
listBoxes.Add("Email", true);
listBoxes.Add("Order_Date"
listBoxes.Add("Title", true);
listBoxes.Add("Unit_Price"
listBoxes.Add("Quantity", true);
BTW, any help at https://www.experts-exchange.com/questions/28562832/Store-meta-data-from-dbml-table-in-a-dictionary-variable.html will be also appreciated.
Mike
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Amazing solution. Thank you very much.
Mike
Mike
Open in new window