In my application I'm calculating the geometric mean a few different places, and would like to have the implementation in one place, so as to cause less confusion for maintainers. For performance reasons I need the calculation to happen in the database, so fetching the data and running GeoMean()
in C# is not an option.
However, I can't figure out how to write an extension method that I can use in my code. The query looks something like this:
data.GroupBy(a => a.Foo)
.Select(a => new {
Id = a.Foo,
Mean = a.GeoMean(b => b.Value)
});
I seem to have figure out I must use a.AsQueryable().GeoMean()
, and an extension method looking something like this:
public static double GeoMean<T>(this IQueryable<T> source, Expression<Func<T, double>> fn)
{
return Math.Exp(source.Average(i => Math.Log(fn(i))));
}
However, since it's expected to return double it complains that fn
is an Expression
. If I change the return type to Expression<Func<double>>
I've merely moved the problem to the Select
in my query, so I probably need to do something to it, but what?
Is this even possible? Should I just accept that I'll have to duplicate the code every time I need the calculation?