【问题标题】:Calling a SQL User-defined function in a LINQ query在 LINQ 查询中调用 SQL 用户定义的函数
【发布时间】:2013-12-06 13:15:31
【问题描述】:

我很难让它发挥作用。我正在尝试在 IQueryable 上使用以下过滤器助手进行半径搜索。在 RadiusSearch 应用之前,还有一组其他过滤器会被应用。顺序并不重要,因为目标是让查询延迟到 ToList() 操作。

public static IQueryable<ApiSearchCommunity> RadiusSearch(this IQueryable<ApiSearchCommunity> communities)
{
    var centerLatitude = 30.421278;
    var centerLongitude = -97.426261;
    var radius = 25;

    return communities.Select(c => new ApiSearchCommunity()
    {
        CommunityId = c.CommunityId,
        City = c.City,
        //Distance = c.GetArcDistance(centerLatitude, centerLongitude, c.Latitude, c.Longitude, radius)
    });
}

我能否以某种方式编写一个像 GetArcDistance 这样的助手,然后在 SQL 上调用 UDF?我试图生成的查询如下

SELECT 
    comms.community_id, 
    comms.city, 
    comms.distance 
FROM (
    SELECT 
        c.community_id, 
        c.city, 
        dbo.udf_ArcDistance(
            30.421278,-97.426261, 
            c.community_latitude,
            c.community_longitude
        ) AS distance 
    FROM communities c) AS comms 
WHERE comms.distance <= 25 
ORDER BY comms.distance

【问题讨论】:

标签: c# sql linq entity-framework linq-to-entities


【解决方案1】:

好的,我想我理解了这个问题 - 要点是您希望能够调用 SQL UDF 作为 Linq to Entities 查询的一部分。

如果您首先使用数据库或模型:

这篇文章解释了如何做到这一点:http://msdn.microsoft.com/en-us/library/dd456847(VS.100).aspx

总而言之,您首先需要在 xml 编辑器中编辑您的 edmx 文件,在 edmx:StorageModels >> Schema 部分中您需要指定到您的 sql udf 的映射,例如

<Function Name="SampleFunction" ReturnType="int" Schema="dbo">
    <Parameter Name="Param" Mode="In" Type="int" />
</Function>

然后你需要在某处创建一个带有 EdmFunction 属性的静态函数,如下所示:

public static class ModelDefinedFunctions
{
    [EdmFunction("TestDBModel.Store", "SampleFunction")]
    public static int SampleFunction(int param)
    {
      throw new NotSupportedException("Direct calls are not supported.");
    }
}

此方法将在实体框架查询时映射到 UDF。第一个属性参数是 store 命名空间 - 您可以在 edmx xml 文件中的 Schema 元素中找到它(查找命名空间)。第二个参数是 udf 的名称。

然后你可以这样称呼它:

var result = from s in context.UDFTests
            select new
            {
                TestVal = ModelDefinedFunctions.SampleFunction(22)
            };

希望这会有所帮助。

【讨论】:

  • 您应该能够将其作为任何 IQueryable 的一部分来调用 - 当实体框架随后评估您的表达式时,它将从属性映射中知道它应该在该场景中使用 SQL UDF。您目前在哪里定义了 GetArcDistance 方法?
【解决方案2】:

如果您使用 Code-First 方法,那么您不能随意调用 UDF(从 EF6 开始) - 这里是 proofanother one。您只能以 part of your SQL query 的身份调用 UDF:

bool result = FooContext.CreateQuery<bool>(
    "SELECT VALUE FooModel.Store.UserDefinedFunction(@someParameter) FROM {1}",
    new ObjectParameter("someParameter", someParameter)
).First();

这是丑陋的 IMO 并且容易出错。

另外 - 这个MSDN 页面说:

调用自定义函数的过程需要三个基本步骤:

  1. 在您的概念模型中定义一个函数或在您的存储模型中声明一个函数

这实质上意味着您需要使用Model-First 方法来调用UDF。

【讨论】:

  • 我使用的是模型优先。
  • 好的——那么@Matt 的答案就是你所需要的。我会保留我的答案,以防有人搜索。
  • 是的,我正在搜索 Code first 版本,我将发布似乎需要解决的问题...创建一个内联 sql 调用并返回所需的值
猜你喜欢
  • 1970-01-01
  • 2013-11-07
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多