Solved

dynamic LINQ string... c#

Posted on 2014-11-16
16
284 Views
Last Modified: 2016-02-15
At line 1 below, lb.ID may contain lslCity or lstState. Variable filedName at the same line, therefore, could contain "City" or "State" (field names).

Question: How can I insert filedName to replace City at lines 3 and 5 with filedName ?

I see that  filedName is string not a field type. I do not know how to cast and convert to filed name,

This way, I will be able to use one LINQ string for two controls.
          string filedName = lb.ID.Substring(3);
           ListItem[] outputs = (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(outputs);

Open in new window

0
Comment
Question by:Mike Eghtebas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 3
16 Comments
 
LVL 11

Expert Comment

by:louisfr
ID: 40446483
You can get a property value by name using reflection.
from output in wscgsContext.Searches
orderby (string)output.GetType().GetProperty(filedName).GetValue(output)
group output by output.City into theGroup
select new ListItem(theGroup.FirstOrDefault().City)

Open in new window


You can also create dynamic expressions with the methods found in the Expression class. With T being the type of items in wscgsContext.Searches
ParameterExpression o = Expression.Parameter(typeof(T));
Func<T, string> orderByExpression = Expression.Lambda<Func<T, string>>(Expression.Property(o, filedName), o);

Open in new window

You can then pass the expression to the OrderBy method:
from output in wscgsContext.Searches.OrderBy(orderByExpression)
group output by output.City into theGroup
select new ListItem(theGroup.FirstOrDefault().City)

Open in new window

0
 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40446497
Hi louisfr,

Thank you for the education. I really appreciate it. I see that City exists in the 1st and 3rd code piece. I was expecting to have fieldName somehow utilized instead.

Sorry for my typo in fieldName, I had filedName instead.

Question: How can I change section 1 and 3 to make them independent of field name City?

Mike

I am try now this:
ListItem[] outputs=from output in wscgsContext.Searches
orderby (string)output.GetType().GetProperty(filedName).GetValue(output)
group output by output.GetProperty(filedName) into theGroup
select new ListItem(theGroup.FirstOrDefault().GetProperty(filedName));

Open in new window


Line 3 has the following error at GetProperty:
'Search' does not contain a definition for 'GetProperty' and no extension method 'GetProperty' accepting a first argument of type 'Search' could be found (are you missing a using directive or an assembly reference?)

I also tried to use ParameterExpression o to plug in place of the field, the following image shows where I am getting errors:errors
Here is another image attempting to utilize section 2 with section 3:error2
0
 
LVL 28

Assisted Solution

by:Ark
Ark earned 150 total points
ID: 40446584
private static object GetPropertyValue(object obj, string property)
{
    System.Reflection.PropertyInfo propertyInfo=obj.GetType().GetProperty(property);
    return propertyInfo.GetValue(obj, null);
}
string filedName = lb.ID.Substring(3);
ListItem[] outputs = (from output in wscgsContext.Searches
        orderby  GetPropertyValue(output, fieldName)
        group output by GetPropertyValue(output, fieldName) into theGroup
        select new ListItem(GetPropertyValue(theGroup.FirstOrDefault(), fieldName))).ToArray();
lb.Items.AddRange(outputs);

Open in new window

0
More Than Just A Video Library

Train for your certification. Learn the latest DevOps tools. Grow your skillset to do better work.

At Linux Academy, we release new training modules every week so you'll always be up to date on the latest tech.

 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40446649
Hi Ark,

There is and error in line 9 (or line 12 below) at : The name 'fieldName' does not exist in the current context.
   private static object GetPropertyValue(object obj, string property)
    {
        System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(property);
        return propertyInfo.GetValue(obj, null);
    }
    private void LoadListBoxes(ListBox lb)
    {
           lb.Items.Clear();
           string filedName = lb.ID.Substring(3);
           ListItem[] outputs = (from output in wscgsContext.Searches
                                 orderby GetPropertyValue(output, filedName)
                                 group output by GetPropertyValue(output, fieldName) into theGroup
                                 select new ListItem(GetPropertyValue(theGroup.FirstOrDefault(), fieldName))).ToArray();
           lb.Items.AddRange(outputs);

Open in new window

0
 
LVL 28

Expert Comment

by:Ark
ID: 40446650
oops, sorry
string filedName = lb.ID.Substring(3);
should be
string fieldName = lb.ID.Substring(3);
0
 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40446658
Now I have two errors:
private static object GetPropertyValue(object obj, string property)
    {
        System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(property);
        return propertyInfo.GetValue(obj, null);
    }
    private void LoadListBoxes(ListBox lb)
    {
           lb.Items.Clear();
           string fieldName = lb.ID.Substring(3);
           ListItem[] outputs = (from output in wscgsContext.Searches
                                 orderby GetPropertyValue(output, fieldName)
                                 group output by GetPropertyValue(output, fieldName) into theGroup
                                 select new ListItem(GetPropertyValue(theGroup.FirstOrDefault(), fieldName))).ToArray();
           lb.Items.AddRange(outputs);

Open in new window


Both at line 13:
select new ListItem(GetPropertyValue(t
Argument 1: cannot convert from 'object' to 'string'

select new ListItem(GetPropertyValue(t
The best overloaded method match for 'System.Web.UI.WebControls.ListItem.ListItem(string)' has some invalid arguments
0
 
LVL 28

Expert Comment

by:Ark
ID: 40446664
Either convert GetPropertyValue return value ( return propertyInfo.GetValue(obj, null).ToString()
or
GetPropertyValue(theGroup.FirstOrDefault(), fieldName).ToString()
0
 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40446675
With: return propertyInfo.GetValue(obj, null).ToString()
no change, the same old errors:error4
With: GetPropertyValue(theGroup.FirstOrDefault(), fieldName).ToString();
Cannot order by type 'System.Object'.
0
 
LVL 11

Expert Comment

by:louisfr
ID: 40446693
I hadn't paid attention to that second use of City.
Ark has shown you how to use GetProperty.

To use the expression, you need to put the right type where I used T. I just used T as a placeholder because I didn't know what is the type of wscgsContext.Searches. While reflection can work on unknown types and check the existence of a property at access time, expressions check it when the expression is created and need to know on which type they're working.
The type of orderByExpression was wrong. I could have called Compile to create a delegate and use it as a method to get a cleaner code. Here is new code. Replace T with the right type.
ParameterExpression o = Expression.Parameter(typeof(T));
Func<T, string> getField = Expression.Lambda<Func<T, 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();

Open in new window

0
 
LVL 11

Expert Comment

by:louisfr
ID: 40446697
Either the GetPropertyValue method must be changed to return string
private static string GetPropertyValue(object obj, string property)

Open in new window

or you have to cast its result to string when you call it
(string)GetPropertyValue( ..... )

Open in new window

0
 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40446710
re:> Replace T with the right type.

After Add New Item, Linq to SQL classes, I dropped table Search to .dbml file in order to use the following code. The database in use is a SQL Server database. I do not know how one determines the type to replace with T as you are mentioning. I have lot to learn and happy to learn all.

 WSCGSoftwareDataContext wscgsContext = new WSCGSoftwareDataContext(cnn);
0
 
LVL 11

Expert Comment

by:louisfr
ID: 40446736
Move your mouse over the Searches property in your LINQ query. Its type should appear.
0
 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40447444
re:> Move your mouse over the Searches property in your LINQ query. Its type should appear.

I did this; it read: WSCGSoftwareDataContext.Searches , I dropped Searches and replaced the Ts with only WSCGSoftwareDataContext. I got the following 3 errors:

error5
FYI: With  WSCGSoftwareDataContext.Searches replacing the Ts I got more errors.
0
 
LVL 11

Accepted Solution

by:
louisfr earned 350 total points
ID: 40447473
It should read "xxxxx WSCGSoftwareDataContext.Searches" or something like that. The type is the xxxxx which precedes the name of the property.
You can also click on the "Searches" word and press F12 to go the definition of the property.
0
 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40447520
I have:

Table <Search> WSCGSoftwareDataContext.Searches

Shall I replace Ts with:
Table
<Search>
Search
Table <Search>

I tired all, after a response from you, I will report the result.

Thanks,

Mike

I tried Table <Search>, I got the following errors:

1      'System.Func<System.Data.Linq.Table<Search>,string>' is a 'type' but is used like a 'variable'
3.      Argument 1: cannot convert from 'Search' to 'System.Data.Linq.Table<Search>'      
2.      Delegate 'System.Func<System.Data.Linq.Table<Search>,string>' has some invalid arguments

Using F12 on Searches takes me to:
public System.Data.Linq.Table<Search> Searches
0
 
LVL 34

Author Comment

by:Mike Eghtebas
ID: 40447639
I will close this question. We have made good progress. It is continued at:
http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_28563821.html
0

Featured Post

Enroll in June's Course of the Month

June’s Course of the Month is now available! Experts Exchange’s Premium Members, Team Accounts, and Qualified Experts have access to a complimentary course each month as part of their membership—an extra way to sharpen your skills and increase training.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Come and listen to Percona CEO Peter Zaitsev discuss what’s new in Percona open source software, including Percona Server for MySQL (https://www.percona.com/software/mysql-database/percona-server) and MongoDB (https://www.percona.com/software/mongo-…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…

691 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question