I have the following function that is extracting me distinct values based on the properties of an object, here Client.
public List<DistinctValue> GetDistinctValues(string propertyName)
{
//how should I specify the keySelector ?
Func<string, object> keySelector = item => propertyName;
var list = new List<DistinctValue>();
var values = this.ObjectContext.Clients.Select(CreateSelectorExpression
(propertyName)).Distinct().OrderBy(keySelector);
int i = 0;
foreach (var value in values)
{
list.Add(new DistinctValue() { ID = i, Value = value });
i++;
}
return list;
}
private static Expression<Func<Client, string>> CreateSelectorExpression
(string propertyName)
{
var paramterExpression = Expression.Parameter(typeof(Client));
return (Expression<Func<Client, string>>)Expression.Lambda(
Expression.PropertyOrField(paramterExpression, propertyName),
paramterExpression);
}
public class DistinctValue
{
[Key]
public int ID { get; set; }
public string Value { get; set; }
}
I'm doing this because I do not know in before which property values I'll need to extract. It's working, just the result is not sorted.
Can you please help me correct the sorting to make the OrderBy work as expected?
The properties are strings and I don't need to chain the sorting. I don't need to specify the sorting order either.
Thanks a lot in advance, John.
Your keySelector
currently returns the same string for each (the property name); and since LINQ is typically a stable sort, this results in no overall change. Since you have already projected to the string values, you can simply use a trivial x=>x
mapping here:
var values = this.ObjectContext.Clients.Select(
CreateSelectorExpression(propertyName)).Distinct().OrderBy(x => x);
to order by the items themselves.
Thanks for the elegant solution. I further expanded upon the CreateSelectorExpression method so it can be leveraged outside of the Client class in the example above.
public static Expression<Func<T, string>> CreateSelectorExpression<T>(string propertyName)
{
var paramterExpression = Expression.Parameter(typeof(T));
return (Expression<Func<T, string>>)Expression.Lambda(Expression.PropertyOrField(paramterExpression, propertyName),
paramterExpression);
}
Usage
Func<IQueryable<YourEntity>, IOrderedQueryable<YourEntity>> orderBy = o => o.OrderByDescending(CreateSelectorExpression<YourEntity>("Entity Property Name"));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With