public static Expression <Func <T, double> > CalculateDistanceFrom <T>(double originLatitude, double originLongitude, string latitudePropertyName, string longitudePropertyName, DistanceUnit distanceUnit) { var earthsRadiusConstantExpression = Expression.Constant(GeoCalculator.GetRadius(distanceUnit)); var inputExpression = Expression.Parameter(typeof(T), "x"); var originLatitudeExpression = Expression.Constant(originLatitude); var originLongitudeExpression = Expression.Constant(originLongitude); var destinationLatitudeExpression = Expression.Convert(Expression.Property(inputExpression, latitudePropertyName), typeof(double)); var destinationLongitudeExpression = Expression.Convert(Expression.Property(inputExpression, longitudePropertyName), typeof(double)); if (originLatitude < -90 || originLatitude > 90 || originLongitude < -180 || originLongitude > 180) { return(Expression.Lambda <Func <T, double> >(Expression.Constant(-1.0), inputExpression)); } return(Expression.Lambda <Func <T, double> >( Expression.Multiply( earthsRadiusConstantExpression, Expression.Multiply( Expression.Constant(2.0), Expression.Call(_asin, // MIN isn't supported in SQL // Tested all (4B+) combinations of valid Lat/Long and calculation was never greater than 1 //Expression.Call(_min, // Expression.Constant(1.0), Expression.Call(_sqrt, Expression.Add( Expression.Call(_pow, Expression.Call(_sin, Expression.Divide( originLatitudeExpression.DiffRadiansExpression(destinationLatitudeExpression), Expression.Constant(2.0) ) ), Expression.Constant(2.0) ), Expression.Multiply( Expression.Call(_cos, originLatitudeExpression.ToRadiansExpression()), Expression.Multiply( Expression.Call(_cos, destinationLatitudeExpression.ToRadiansExpression()), Expression.Call(_pow, Expression.Call(_sin, Expression.Divide( originLongitudeExpression.DiffRadiansExpression(destinationLongitudeExpression), Expression.Constant(2.0) ) ), Expression.Constant(2.0) ) ) ) ) ) //) ) ) ), inputExpression)); }