方法: モデル定義関数をオブジェクト メソッドとして呼び出す

ここでは、モデル定義関数を ObjectContext オブジェクトのメソッドまたはカスタム クラスの静的メソッドとして呼び出す方法について説明します。 モデル定義関数は、概念モデルで定義される関数です。 このトピックで説明する手順は、これらの関数を LINQ to Entities クエリから呼び出すのではなく、直接呼び出す方法を示すものです。 モデル定義関数を LINQ to Entities クエリに呼び出す方法の詳細については、「方法:クエリを使用してモデル定義関数を呼び出す」を参照してください。

モデル定義関数を ObjectContext メソッドとして呼び出す場合も、カスタム クラスの静的メソッドとして呼び出す場合も、ます EdmFunctionAttribute でメソッドをモデル定義関数にマップする必要があります。 ただし、ObjectContext クラスのメソッドを定義するときには、QueryProvider プロパティを使用して LINQ プロバイダーを公開する必要があります。それに対して、カスタム クラスの静的メソッドを定義するときには、Provider プロパティを使用して LINQ プロバイダーを公開する必要があります。 詳細については、下の手順の後に示した例を参照してください。

下の手順は、モデル定義関数を ObjectContext オブジェクトのメソッドおよびカスタム クラスの静的メソッドとして呼び出す方法の概要を示したものです。 詳細な手順は、その後の例で示します。 この手順では、関数を概念モデルで定義済みであると想定します。 詳細については、概念モデルでカスタム関数を定義する」を参照してください。

モデル定義関数を ObjectContext オブジェクトのメソッドとして呼び出すには

  1. ソース ファイルを追加して、部分クラスを拡張します。このクラスは、ObjectContext クラスから派生したものであり、Entity Framework ツールによって自動生成されます。 CLR スタブを別のソース ファイルで定義すると、ファイルを再生成しても変更内容が失われません。

  2. 共通言語ランタイム (CLR) メソッドを、次のことを行う ObjectContext クラスに追加します。

    • 概念モデルで定義された関数にマップします。 メソッドをマップするには、ユーザーが EdmFunctionAttribute をメソッドに適用する必要があります。 属性の NamespaceName パラメーターと FunctionName パラメーターが、それぞれ概念モデルの名前空間と概念モデルの関数名であることに注意してください。 LINQ の関数名解決では、大文字と小文字が区別されます。

    • Execute プロパティによって返される QueryProvider メソッドの結果を返します。

  3. メソッドを ObjectContext クラスのインスタンスのメンバーとして呼び出します。

モデル定義関数をカスタム クラスの静的メソッドとして呼び出すには

  1. クラスを次のことを行う静的メソッドでアプリケーションに追加します。

    • 概念モデルで定義された関数にマップします。 メソッドをマップするには、ユーザーが EdmFunctionAttribute をメソッドに適用する必要があります。 属性の NamespaceName パラメーターと FunctionName パラメーターが、それぞれ概念モデルの名前空間と概念モデルの関数名であることに注意してください。

    • IQueryable 引数を受け取ります。

    • Execute プロパティによって返される Provider メソッドの結果を返します。

  2. メソッドをカスタム クラスの静的メソッドのメンバーとして呼び出します。

例 1

モデル定義関数を ObjectContext オブジェクトのメソッドとして呼び出す

次の例で、モデル定義関数を ObjectContext オブジェクトのメソッドとして呼び出す方法を説明します。 この例では、AdventureWorks Sales Model を使用します。

指定製品の製品収益を返す下の概念モデル関数について考察してください (関数を概念モデルに追加する方法については、「方法:概念モデルでカスタム関数を定義する」を参照してください。)

<Function Name="GetProductRevenue" ReturnType="Edm.Decimal">
  <Parameter Name="productID" Type="Edm.Int32" />
  <DefiningExpression>
    SUM( SELECT VALUE((s.UnitPrice - s.UnitPriceDiscount)  * s.OrderQty)
    FROM AdventureWorksEntities.SalesOrderDetails as s
    WHERE s.ProductID = productID)
  </DefiningExpression>
</Function>

例 2

次のコードでは、メソッドを上の概念モデル関数にマップする AdventureWorksEntities クラスに追加します。

public partial class AdventureWorksEntities : ObjectContext
{
    [EdmFunction("AdventureWorksModel", "GetProductRevenue")]
    public decimal? GetProductRevenue(int productId)
    {
        return this.QueryProvider.Execute<decimal?>(Expression.Call(
            Expression.Constant(this),
            (MethodInfo)MethodInfo.GetCurrentMethod(),
            Expression.Constant(productId, typeof(int))));
    }
}
Partial Public Class AdventureWorksEntities
    Inherits ObjectContext

    <EdmFunction("AdventureWorksModel", "GetProductRevenue")>
    Public Function GetProductRevenue(ByVal details As _
                    IQueryable(Of SalesOrderDetail)) As _
                    System.Nullable(Of Decimal)
        Return Me.QueryProvider.Execute(Of System.Nullable(Of Decimal)) _
            (Expression.[Call](Expression.Constant(Me), _
            DirectCast(MethodInfo.GetCurrentMethod(), MethodInfo), _
            Expression.Constant(details, GetType(IQueryable(Of SalesOrderDetail)))))
    End Function
End Class

例 3

次のコードでは、上のメソッドを呼び出して、指定製品の製品収益を表示します。

using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    int productId = 776;

    Console.WriteLine(AWEntities.GetProductRevenue(productId));
}
Using AWEntities As New AdventureWorksEntities()

    Dim productId As Integer = 776

    Dim details = From s In AWEntities.SalesOrderDetails _
                  Where s.ProductID = productId _
                  Select s

    Console.WriteLine(AWEntities.GetProductRevenue(details))
End Using

例 4

次の例で、コレクション (IQueryable<T> オブジェクトとして) を返すモデル定義関数を呼び出す方法を説明します。 指定された製品 ID に関して SalesOrderDetails をすべて返す下の概念モデル関数について考察してください。

<Function Name="GetDetailsById" 
          ReturnType="Collection(AdventureWorksModel.SalesOrderDetail)">
  <Parameter Name="productID" Type="Edm.Int32" />
  <DefiningExpression>
    SELECT VALUE s
    FROM AdventureWorksEntities.SalesOrderDetails AS s
    WHERE s.ProductID = productID
  </DefiningExpression>
</Function>

例 5

次のコードでは、メソッドを上の概念モデル関数にマップする AdventureWorksEntities クラスに追加します。

public partial class AdventureWorksEntities : ObjectContext
{
    [EdmFunction("AdventureWorksModel", "GetDetailsById")]
    public IQueryable<SalesOrderDetail> GetDetailsById(int productId)
    {
        return this.QueryProvider.CreateQuery<SalesOrderDetail>(Expression.Call(
            Expression.Constant(this),
            (MethodInfo)MethodInfo.GetCurrentMethod(),
            Expression.Constant(productId, typeof(int))));
    }
}
Partial Public Class AdventureWorksEntities
    Inherits ObjectContext
    <EdmFunction("AdventureWorksModel", "GetDetailsById")> _
    Public Function GetDetailsById(ByVal productId As Integer) _
            As IQueryable(Of SalesOrderDetail)
        Return Me.QueryProvider.CreateQuery(Of SalesOrderDetail) _
            (Expression.[Call](Expression.Constant(Me), _
             DirectCast(MethodInfo.GetCurrentMethod(), MethodInfo), _
             Expression.Constant(productId, GetType(Integer))))
    End Function
End Class

例 6

次のコードは、メソッドを呼び出します。 返された IQueryable<T> クエリがさらに絞り込まれて、各 SalesOrderDetail のライン合計を返すことに注意してください。

using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    int productId = 776;

    var lineTotals = AWEntities.GetDetailsById(productId).Select(d =>d.LineTotal);

    foreach(var lineTotal in lineTotals)
    {
        Console.WriteLine(lineTotal);
    }
}
Using AWEntities As New AdventureWorksEntities()
    Dim productId As Integer = 776

    Dim lineTotals = AWEntities.GetDetailsById(productId).[Select](Function(d) d.LineTotal)

    For Each lineTotal In lineTotals
        Console.WriteLine(lineTotal)
    Next

例 7

モデル定義関数をカスタム クラスの静的メソッドとして呼び出す

次の例で、モデル定義関数をカスタム クラスの静的メソッドとして呼び出す方法を説明します。 この例では、AdventureWorks Sales Model を使用します。

Note

ユーザーが、モデル定義関数をカスタム クラスの静的メソッドとして呼び出すときには、モデル定義関数はコレクションを受け取って、コレクションの値の集計結果を返す必要があります。

SalesOrderDetail コレクションの製品収益を返す下の概念モデル関数について考察してください (関数を概念モデルに追加する方法については、「方法:概念モデルでカスタム関数を定義する」を参照してください。)

<Function Name="GetProductRevenue" ReturnType="Edm.Decimal">
  <Parameter Name="details" Type="Collection(AdventureWorksModel.SalesOrderDetail)" />
  <DefiningExpression>
    SUM( SELECT VALUE((s.UnitPrice - s.UnitPriceDiscount)  * s.OrderQty)
    FROM details as s)
  </DefiningExpression>
</Function>

例 8

次のコードでは、上の概念モデル関数にマップする静的メソッドを持つアプリケーションにクラスを追加します。

public class MyClass
{
    [EdmFunction("AdventureWorksModel", "GetProductRevenue")]
    public static decimal? GetProductRevenue(IQueryable<SalesOrderDetail> details)
    {
        return details.Provider.Execute<decimal?>(Expression.Call(
            (MethodInfo)MethodInfo.GetCurrentMethod(),
            Expression.Constant(details, typeof(IQueryable<SalesOrderDetail>))));
    }
}
Public Class [MyClass]
    <EdmFunction("AdventureWorksModel", "GetProductRevenue")> _
    Public Shared Function GetProductRevenue(ByVal details As _
                IQueryable(Of SalesOrderDetail)) As _
                System.Nullable(Of Decimal)
        Return details.Provider.Execute(Of System.Nullable(Of Decimal)) _
            (Expression.[Call](DirectCast(MethodInfo.GetCurrentMethod(), MethodInfo), _
            Expression.Constant(details, GetType(IQueryable(Of SalesOrderDetail)))))
    End Function
End Class

例 9

次のコードでは、上のメソッドを呼び出して、SalesOrderDetail コレクションの製品収益を表示します。

using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    int productId = 776;

    var details = from s in AWEntities.SalesOrderDetails
                  where s.ProductID == productId select s;

    Console.WriteLine(MyClass.GetProductRevenue(details));
}
Using AWEntities As New AdventureWorksEntities()
    Dim productId As Integer = 776

    Dim details = From s In AWEntities.SalesOrderDetails _
                  Where s.ProductID = productId _
                  Select s

    Console.WriteLine([MyClass].GetProductRevenue(details))
End Using

関連項目