C# 向EntityFramework添加自定义函数

C# 向EntityFramework添加自定义函数,c#,entity-framework,linq,C#,Entity Framework,Linq,我想在我的项目中添加一个函数,这样我可以过滤我的数据 我希望该函数返回两个GPS位置之间的距离(以公里为单位) 到目前为止,我已经做了: 在我的edmx中的ConceptualModels>Schema中添加了以下内容: <Function Name="DistanceBetweenTwoPositions" ReturnType="Edm.Double"> <Parameter Name="latitude_1" Type="Edm.Double" /&g

我想在我的项目中添加一个函数,这样我可以过滤我的数据

我希望该函数返回两个GPS位置之间的距离(以公里为单位)

到目前为止,我已经做了: 在我的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>
并在我的代码中调用它:

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)
                                ;
双纬度=0;
双经度=0;
var请求=(来自数据库房屋中的房屋)
选择
刚出现的
{
房屋
DistanceFromUser=BackbonedEntitiesLocal.两个位置之间的距离(纬度、经度、house.latitude.Value)、house.latitude.Value))
})
.其中(u=>u.DistanceFromUser u.DistanceFromUser)
;
但它不起作用,我得到以下例外:

准备函数的定义时出错 “数据模型。两个位置之间的距离”。有关详细信息,请参见内部异常 细节

内部异常:

System.Data.Entity.Core.EntitySqlException: “两个位置之间的距离”无法解析为有效类型或 作用靠近简单标识符,第2行,第13列。在 System.Data.Entity.Core.Common.EntitySql.SemanticAnalyzer.ConvertMethodExpr(MethodExpr methodExpr、布尔includeInlineFunctions、SemanticResolver sr)位于 System.Data.Entity.Core.Common.EntitySql.Semanticalyzer.ConvertMethodExpr(节点 expr,semanticsolver sr)在 System.Data.Entity.Core.Common.EntitySql.Semanticalyzer.Convert(节点 astExpr,SemanticResolver sr)在 System.Data.Entity.Core.Common.EntitySql.Semanticalyzer.ConvertValueExpressionAllowUntypedNulls(节点 astExpr,SemanticResolver sr)在 System.Data.Entity.Core.Common.EntitySql.Semanticalyzer.ConvertQueryStatementToDbExpression(语句 astStatement,semanticSolver sr,List
1&functionDefs)位于
System.Data.Entity.Core.Common.EntitySql.Semanticalyzer.AnalyzeQueryCommand(节点
astExpr)在

System.Data.Entity.Core.Common.EntitySql.CqlQuery.

我的第一个观察结果是,这是否应该出现在EF映射中?从概念上讲,位置是否知道如何计算到另一个任意点的距离?实际上,我把所有这些都放在一个叫做“距离计算器”的单独的类中,它取2个任意点,并返回一个距离。然后可以在具体化查询结果后调用它

实现中的问题是无法将函数转换回SQL。EF不知道如何将这些Math.*函数转换为SQL。首先将所有Math.*调用替换为中的相应调用。这个班有

提供在中调用函数的公共语言运行库(CLR)方法 LINQ中的数据库用于实体查询


这将为EF生成可用的SQL。

如果使用EF6+,则可以将两个位置之间的距离逻辑作为SQL标量值函数移动

更新EF模型并将标量值函数导入模型

如果您以这种方式映射它,您将能够像使用它一样在查询中使用它


希望对您有所帮助。

您是否尝试过将DbFunctionAttribute更改为EdmFunctionAttribute?可能是相关问题
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)
                                ;