I would like to add a function in my project so that I can filter my data.
I would like that function to returns the distance in kms between 2 GPS positions.
So far I've done : added this in my edmx in the ConceptualModels>Schema :
<Function Name="DistanceBetweenTwoPositions" ReturnType="Edm.Double">
<Parameter Name="latitude_1" Type="Edm.Double" />
<Parameter Name="longitude_1" Type="Edm.Double" />
<Parameter Name="latitude_2" Type="Edm.Double" />
<Parameter Name="longitude_2" Type="Edm.Double" />
<DefiningExpression>
DistanceBetweenTwoPositions(latitude_1, longitude_1, latitude_2, longitude_2)
</DefiningExpression>
</Function>
Created a partial class with the same name to be able to define that function :
[DbFunctionAttribute("DataModel", "DistanceBetweenTwoPositions")]
public static double DistanceBetweenTwoPositions(double latitude_1, double longitude_1, double latitude_2, double longitude_2)
{
var rlat1 = Math.PI * latitude_1 / 180;
var rlat2 = Math.PI * latitude_2 / 180;
var rlon1 = Math.PI * longitude_1 / 180;
var rlon2 = Math.PI * longitude_2 / 180;
var theta = longitude_1 - longitude_2;
var rtheta = Math.PI * theta / 180;
var dist = Math.Sin(rlat1) * Math.Sin(rlat2) + Math.Cos(rlat1) * Math.Cos(rlat2) * Math.Cos(rtheta);
dist = Math.Acos(dist);
dist = dist * 180 / Math.PI;
dist = dist * 60 * 1.1515;
dist = dist * 1.609344; // Conversion to kms
return dist;
}
And called it in my code :
double latitude = 0;
double longitude = 0;
var request = (from house in db.Houses
select
new
{
house,
DistanceFromUser = BackboneDBEntitiesLocal.DistanceBetweenTwoPositions(latitude, longitude, house.Latitude.Value), house.Longitude.Value))
})
.Where(u=>u.DistanceFromUser <= range)
.OrderBy(u=>u.DistanceFromUser)
;
But it doesn't work I get the following exception :
An error occurred while preparing definition of the function 'DataModel.DistanceBetweenTwoPositions'. See the inner exception for details.
InnerException :
System.Data.Entity.Core.EntitySqlException: 'DistanceBetweenTwoPositions' cannot be resolved into a valid type or function. Near simple identifier, line 2, column 13. at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertMethodExpr(MethodExpr methodExpr, Boolean includeInlineFunctions, SemanticResolver sr) at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertMethodExpr(Node expr, SemanticResolver sr) at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.Convert(Node astExpr, SemanticResolver sr) at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertValueExpressionAllowUntypedNulls(Node astExpr, SemanticResolver sr) at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertQueryStatementToDbExpression(Statement astStatement, SemanticResolver sr, List
1& functionDefs) at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.AnalyzeQueryCommand(Node astExpr) at System.Data.Entity.Core.Common.EntitySql.CqlQuery.<AnalyzeQueryExpressionSemantics>b__8(SemanticAnalyzer analyzer, Node astExpr) at System.Data.Entity.Core.Common.EntitySql.CqlQuery.AnalyzeSemanticsCommon[TResult](Node astExpr, Perspective perspective, ParserOptions parserOptions, IEnumerable
1 parameters, IEnumerable1 variables, Func
3 analysisFunction) at System.Data.Entity.Core.Common.EntitySql.CqlQuery.AnalyzeQueryExpressionSemantics(Node astQueryCommand, Perspective perspective, ParserOptions parserOptions, IEnumerable1 parameters, IEnumerable
1 variables) at System.Data.Entity.Core.Common.EntitySql.CqlQuery.<>c__DisplayClass4.b__3(Node astCommand, ParserOptions validatedParserOptions) at System.Data.Entity.Core.Common.EntitySql.CqlQuery.CompileCommon[TResult](String commandText, ParserOptions parserOptions, Func3 compilationFunction) at System.Data.Entity.Core.Common.EntitySql.CqlQuery.CompileQueryCommandLambda(String queryCommandText, Perspective perspective, ParserOptions parserOptions, IEnumerable
1 parameters, IEnumerable1 variables)
1 functionParameters, EdmItemCollection edmItemCollection) at System.Data.Entity.Core.Metadata.Edm.EdmItemCollection.GenerateFunctionDefinition(EdmFunction function) at System.Data.Entity.Core.Common.Utils.Memoizer
at System.Data.Entity.Core.Mapping.ViewGeneration.Utils.ExternalCalls.CompileFunctionDefinition(String functionDefinition, IList2.<>c__DisplayClass2.<Evaluate>b__0() at System.Data.Entity.Core.Common.Utils.Memoizer
2.Result.GetValue()
at System.Data.Entity.Core.Common.Utils.Memoizer`2.Evaluate(TArg arg) at System.Data.Entity.Core.Metadata.Edm.EdmItemCollection.GetGeneratedFunctionDefinition(EdmFunction function) at System.Data.Entity.Core.Metadata.Edm.MetadataWorkspace.GetGeneratedFunctionDefinition(EdmFunction function) at System.Data.Entity.Core.Query.PlanCompiler.ITreeGenerator.Visit(DbFunctionExpression e)
I've been following the answer of that article, thanks to him for the nice explanation : LINQ to Entities does not recognize the method 'Double Parse(System.String)' method, and this method cannot be translated into a store expression