web-dev-qa-db-ja.com

LINQクエリでSQLユーザー定義関数を呼び出す

これを機能させるのに苦労しています。 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
13
Praveen

わかりました。質問は理解できたと思います。その要点は、Linq toEntitiesクエリの一部としてSQLUDFを呼び出せるようにすることです。

これは、最初にデータベースまたはモデルを使用している場合です。

この記事では、その方法について説明します。 http://msdn.Microsoft.com/en-us/library/dd456847(VS.100).aspx

要約すると、最初にxmlエディターでedmxファイルを編集する必要があります。edmx:StorageModels >> Schemaセクションで、SQLudfへのマッピングを指定する必要があります。

<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にマップされます。最初の属性引数はストアの名前空間です。これは、Schema要素のedmx xmlファイルにあります(名前空間を探してください)。 2番目の引数はudfの名前です。

次に、次のように呼び出すことができます。

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

お役に立てれば。

25
Matt Whetton

Code-Firstアプローチを使用する場合、できません必要に応じてUDFを呼び出すことはできません(EF6以降)-ここに 証明 、および 別の1つ 。 UDFの呼び出しは SQLクエリの一部 :としてのみ制限されます。

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

これは醜いIMOでエラーが発生しやすいです。

また-これ [〜#〜] msdn [〜#〜] ページは言う:

カスタム関数を呼び出すプロセスには、次の3つの基本的な手順が必要です。

  1. 概念モデルで関数を定義するか、ストレージモデルで関数を宣言します。

これは基本的に、UDFを呼び出すためにModel-Firstアプローチを使用する必要があることを意味します。

15
avs099