我想在我的项目中添加一个函数,以便我可以过滤我的数据。
我希望该功能能够返回2个GPS位置之间的距离(kms)。
到目前为止,我已经完成了: 在我的edmx中在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>
创建了一个具有相同名称的部分类,以便能够定义该函数:
[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;
}
在我的代码中调用它:
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)
;
但它没有用,我得到以下例外:
准备函数定义时发生错误 &#39; DataModel.DistanceBetweenTwoPositions&#39 ;.查看内部异常 的信息。
InnerException:
System.Data.Entity.Core.EntitySqlException: &#39; DistanceBetweenTwoPositions&#39;无法解析为有效类型或 功能。近简单标识符,第2行,第13列 System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertMethodExpr(MethodExpr methodExpr,Boolean includeInlineFunctions,SemanticResolver sr)at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertMethodExpr(节点 expr,SemanticResolver sr)at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.Convert(节点 astExpr,SemanticResolver sr)at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertValueExpressionAllowUntypedNulls(节点 astExpr,SemanticResolver sr)at System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertQueryStatementToDbExpression(声明 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个参数,IEnumerable1 variables, Func
3 analysisFunction)at System.Data.Entity.Core.Common.EntitySql.CqlQuery.AnalyzeQueryExpressionSemantics(节点 astQueryCommand,Perspective透视图,ParserOptions parserOptions, IEnumerable1 parameters, IEnumerable
1个变量)at System.Data.Entity.Core.Common.EntitySql.CqlQuery&LT;&GT; c__DisplayClass4.b__3(节点 astCommand,ParserOptions validatedParserOptions)at System.Data.Entity.Core.Common.EntitySql.CqlQuery.CompileCommon [TResult](字符串 commandText,ParserOptions parserOptions,Func3 compilationFunction) at System.Data.Entity.Core.Common.EntitySql.CqlQuery.CompileQueryCommandLambda(String queryCommandText, Perspective perspective, ParserOptions parserOptions, IEnumerable
1个参数,IEnumerable1 variables)
1个functionParameters,EdmItemCollection edmItemCollection)at System.Data.Entity.Core.Metadata.Edm.EdmItemCollection.GenerateFunctionDefinition(EdmFunction 功能) 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()
在System.Data.Entity.Core.Common.Utils.Memoizer`2.Evaluate(TArg arg) 在 System.Data.Entity.Core.Metadata.Edm.EdmItemCollection.GetGeneratedFunctionDefinition(EdmFunction 功能) System.Data.Entity.Core.Metadata.Edm.MetadataWorkspace.GetGeneratedFunctionDefinition(EdmFunction 功能) System.Data.Entity.Core.Query.PlanCompiler.ITreeGenerator.Visit(DbFunctionExpression E)
我一直在关注那篇文章的答案,感谢他的好解释:LINQ to Entities does not recognize the method 'Double Parse(System.String)' method, and this method cannot be translated into a store expression
答案 0 :(得分:1)
我的第一个观察是甚至应该在EF映射中?从概念上讲,位置知道如何计算到另一个任意点的距离?我实际把所有这些都放在一个名为DistanceCalculator的单独的类中,该类占用2个任意点并返回一个距离。然后可以在实现查询结果后调用它。
您的实现中的问题是您的函数无法转换回SQL。 EF不知道如何将这些Math。*函数转换为SQL。首先用SqlFunctions中的相应调用替换所有Math。*调用。这个班有
提供调用函数的公共语言运行时(CLR)方法 LINQ to Entities查询中的数据库。
这应该为EF生成可用的SQL。
答案 1 :(得分:0)
如果您使用的是EF6 +,则可以将DistanceBetweenTwoPositions的逻辑移动为SQL标量值函数。
更新您的EF模型并将Scalar值函数导入模型。
如果你以这种方式映射它,你就可以像在拥有它一样在查询中使用它。
希望有所帮助。