当前位置: 首页 > 面试题库 >

如何将带有linq的标量值函数用于实体?

周锐
2023-03-14
问题内容

我有一个标量函数,它获取两点之间的距离,我想用它来查询最接近点的记录。标量函数与linq to sql一起使用,但对EF失败

标量函数

USE [GeoData]
GO

/****** Object:  UserDefinedFunction [dbo].[DistanceBetween]    Script Date: 09/18/2012 19:40:44 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO



CREATE FUNCTION [dbo].[DistanceBetween](@Lat1 as real,
@Long1 as real, @Lat2 as real, @Long2 as real)
RETURNS real
AS
BEGIN

DECLARE @dLat1InRad as float(53);
SET @dLat1InRad = @Lat1;
DECLARE @dLong1InRad as float(53);
SET @dLong1InRad = @Long1;
DECLARE @dLat2InRad as float(53);
SET @dLat2InRad = @Lat2;
DECLARE @dLong2InRad as float(53);
SET @dLong2InRad = @Long2 ;

DECLARE @dLongitude as float(53);
SET @dLongitude = @dLong2InRad - @dLong1InRad;
DECLARE @dLatitude as float(53);
SET @dLatitude = @dLat2InRad - @dLat1InRad;
/* Intermediate result a. */
DECLARE @a as float(53);
SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad)
* COS (@dLat2InRad)
* SQUARE(SIN (@dLongitude / 2.0));
/* Intermediate result c (great circle distance in Radians). */
DECLARE @c as real;
SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a));
DECLARE @kEarthRadius as real;
/* SET kEarthRadius = 3956.0 miles */
SET @kEarthRadius = 6376.5;        /* kms */

DECLARE @dDistance as real;
SET @dDistance = @kEarthRadius * @c;
return (@dDistance);
END

GO

我添加了一个ado.net实体模型,从数据库中更新了模型,并选择了

 <Function Name="DistanceBetween" ReturnType="real" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
      <Parameter Name="Lat1" Type="real" Mode="In" />
      <Parameter Name="Long1" Type="real" Mode="In" />
      <Parameter Name="Lat2" Type="real" Mode="In" />
      <Parameter Name="Long2" Type="real" Mode="In" />
    </Function>

我做了一个局部类并写了这个方法

public partial class GeoDataEntities
{
    [EdmFunction("GeoDataModel.Store", "DistanceBetween")]
    public double DistanceBetween(double lat1, double lon1, double lat2, double lon2)
    {
        throw new NotImplementedException();
    }
}

我尝试了很多次,用此代码查询函数,但出现错误

var NParcel = db.geoAddresses.Where(g=> db.DistanceBetween(21.5,39.5, g.lat,g.lon) < 20);

当我尝试countforeachNParcel时出现此错误

类型为’EFSample.GeoDataEntities’的指定方法’Double
DistanceBetween(Double,Double,Double,Double)’无法转换为LINQ to Entities存储表达式。

和stacktrace

在System.Data.Objects.ELinq.ExpressionConverter.ThrowUnresolvableFunction(Expression
Expression)处System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.FunctionCallTranslator.TranslateFunctionCall(ExpressionConverter
parent,MethodCallExpression call,EdmFunctionAttribute
functionAttribute)在System.Data.Objects.ELinq
System.Data.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter父代,BinaryExpression
linq)在System.Data.Objects.ELinq.ExpressionConion(Expression)(ExpressionConverter。在System.Data.Objects.ELinq处,位于System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression
lambda,DbExpression输入)处。ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter父,MethodCallExpression调用,DbExpression&源,DbExpressionBinding&sourceBinding,DbExpression&lambda)位于System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter
.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter父类,System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression
linq)在System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.AggregateTranslator。在System.Data.Objects.ELinq.ExpressionConverter处调用ExpressionConverter的父方法(调用MethodCallExpression)。System.Data.Objects.ELinq.ExpressionConverter.Convert()(System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable)处的MethodCallTranslator.TypedTranslate(ExpressionConverter
parent,MethodCallExpression linq)1 forMergeOption) at System.Data.Objects.ObjectQuery1.GetResults(Nullable,1 forMergeOption) at System.Data.Objects.ObjectQuery位于System.Linq.Enumerable.Single
[TSource]中的System.Collections.Generic.IEnumerable.GetEnumerator()(IEnumerable
1 source) at System.Linq.Queryable.Count[TSource](IQueryable1源)


问题答案:

这是您的操作方式:

第1步:在edmx中

      <Function Name="DistanceBetween" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
      <CommandText>
        select dbo.DistanceBetween(@lat1,@long1,@lat2,@long2)
      </CommandText>
      <Parameter Name="Lat1" Type="real" Mode="In" />
      <Parameter Name="Long1" Type="real" Mode="In" />
      <Parameter Name="Lat2" Type="real" Mode="In" />
      <Parameter Name="Long2" Type="real" Mode="In" />
    </Function>

步骤2:导入功能

  1. 双击 edmx
  2. 在“模型浏览器”视图中,展开GeoDataModel.Store(可以命名为不同)
  3. 扩张 stored procedures /function
  4. 连按两下 DistanceBetween
  5. Scalars = Single
  6. 点击确定

步骤3:在C#中:

    GeoDataEntities db = new GeoDataEntities();
    var first = db.DistanceBetween(234, 2342, 424, 243).First().Value;

请注意IsComposable="false"ReturnType,不要忘记添加:

      <CommandText>
        select dbo.DistanceBetween(@lat1,@long1,@lat2,@long2)
      </CommandText>

希望能有所帮助。



 类似资料:
  • 问题内容: 我最近一直在 sql server中 搜索等效项,遇到了两件事,这证明是无用的。 __ 我知道这个问题以前曾被提出过,并且得到了公认的答案,但是它并不能像领带 一样 起作用。采用该解决方案如预期不会导致考虑包括数据集的结果集将是它应该是 使用以下样本数据(从此问题中获取): 传统将会导致一个:,和 一个 ( 或 )它应该包括 BOTH 我知道没有内置的等效项,我已经找到了实现它的方法。

  • 我找不到只发送一些标量值和指标的能力! 仪表只允许标记时间点。 通过调用存储函数生成一个值。 cn只增加或减少。 我可以有实体,允许我发送一些我想要的值吗?

  • 我通常使用以下语法按天分组: 现在,我的日期值位于名为的JSONB列中。 这会产生以下错误: 错误:函数日期(未知,文本)不存在第1行:选择日期('day',“extras”- 有没有办法让这一切顺利进行?

  • 问题内容: 我想将带有参数的函数应用于python pandas中的系列: 问题答案: 位置参数添加到系列元素之后。 对于旧版本的pandas: 文档对此进行了清楚的说明。apply方法接受应具有单个参数的python函数。如果要传递更多参数,则应按照在其评论中的建议使用。 一个例子: 你也可以使用传递关键字参数。 另一种方法是创建一个lambda: 但我认为使用partial会更好。

  • 问题内容: 希望您能提供帮助。我正在寻找一种编写稍后插入一个项目的函数的方法。让我给你看一个例子: 我以为我可以在这里提供一个值,一旦我将其替换,那么显然就不那么容易了。我必须更改/添加什么才能使我的功能正常工作?函数如何知道乘法是?谢谢你们的帮助! 问题答案: 系统要求您返回一个函数,但返回的是计算得出的值: 现在将执行您期望的操作,但是如果将其分配给一个值,它可能会更有用,因此可以多次调用它,

  • 假设我有这个命令代码: 我该如何以函数式的方式写这篇文章(就像fold在Scala中做的那样)?