How to get single column with LINQ in anonymous method

2.6k views Asked by At

How to get single column with anonymous method using linq expression. Here's my code and it doesn't work:

public IEnumerable<object> GetPropertyValues<T>(string propName) where T : class
{
    return base.Query<T>().AsEnumerable()
        .Where(x => x.GetType().GetProperty(propName).Name == propName)
        .Select(x => x.GetType().GetProperty(propName).GetValue(x, null));
}

Here's the code in non generic method:

base.Query<Product>().Select(x => x.ProductName).AsEnumerable();

Thanks in advance.

3

There are 3 answers

0
Sergey Kalinichenko On BEST ANSWER

This condition is incorrect, because when the property propName is missing, it crashes, rather than returning false:

.Where(x => x.GetType().GetProperty(propName).Name == propName)

If you wanted to say "the dynamic type has the property propName", a proper condition for it would look like this:

.Where(x => x.GetType().GetProperty(propName) != null)

Note that this is necessary only when some, but not all, subclasses of T have the desired property propName. If the property is present in the T itself, you could get property upfront, and do the rest of the query like this:

var theProp = typeof(T)..GetProperty(propName);
return base.Query<T>().AsEnumerable().Select(x => theProp.GetValue(x, null));
2
ChaseMedallion On

Once you call AsEnumerable() all further filtering will happen in memory rather than SQL. Thus, you could do:

var prop = typeof(T).GetProperty(propName);
return base.Query<T>().AsEnumerable().Select(t => prop.GetValue(t));

but this will select all columns of T into memory before filtering down to just one. To do the filtering in SQL, you'll need to dynamically construct an expression:

var prop = typeof(T).GetProperty(propName);
var parameter = Expression.Parameter(typeof(T));
var memberAccess = Expression.MakeMemberAccess(parameter, prop);
var selector = Expression.Lambda<Func<T, TProperty>>(memberAccess, parameter);
return base.Query<T>().Select(selector);
0
cwharris On

For an enumeration of any type of objects...

public static IEnumerable<Object> Pluck<Object>(this IEnumerable<Object> source, string propName)
{
    return source
        .Select(x => new {
            obj: x
            prop: x.GetType().GetProperty(propName)
        })
        .Where(x => x.prop != null)
        .Select(x => x.prop.GetValue(x.obj));
};

For an enumeration of a single type of object...

public static IEnumerable<Object> Pluck<T>(this IEnumerable<T> source, string, propName)
{
    var prop = typeof(T).GetProperty(propName);
    return prop == null
         ? Enumerable.Empty<Object>()
         : source.Select(x => prop.GetValue(x));
};