dynamic LINQ string... c#

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

LVL 34
Mike EghtebasDatabase and Application DeveloperAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

louisfrCommented:
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
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
ArkCommented:
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
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
ArkCommented:
oops, sorry
string filedName = lb.ID.Substring(3);
should be
string fieldName = lb.ID.Substring(3);
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
ArkCommented:
Either convert GetPropertyValue return value ( return propertyInfo.GetValue(obj, null).ToString()
or
GetPropertyValue(theGroup.FirstOrDefault(), fieldName).ToString()
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
louisfrCommented:
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
louisfrCommented:
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
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
louisfrCommented:
Move your mouse over the Searches property in your LINQ query. Its type should appear.
0
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
louisfrCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
Mike EghtebasDatabase and Application DeveloperAuthor Commented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.