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

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

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

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

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

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

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

    • 概念モデルで定義された関数にマップします。 To map the method, you must apply an EdmFunctionAttribute to the method. 属性の NamespaceName パラメーターと FunctionName パラメーターが、それぞれ概念モデルの名前空間と概念モデルの関数名であることに注意してください。 LINQ の関数名解決では、大文字と小文字が区別されます。

    • Returns the results of the Execute method that is returned by the QueryProvider property.

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

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

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

    • 概念モデルで定義された関数にマップします。 To map the method, you must apply an EdmFunctionAttribute to the method. 属性の NamespaceName パラメーターと FunctionName パラメーターが、それぞれ概念モデルの名前空間と概念モデルの関数名であることに注意してください。

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

    • Returns the results of the Execute method that is returned by the Provider property.

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

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

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

指定製品の製品収益を返す下の概念モデル関数について考察してください (関数を概念モデルに追加する方法については、「How to: Define Custom Functions in the Conceptual 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>

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

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
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))));
    }
}

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

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
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    int productId = 776;

    Console.WriteLine(AWEntities.GetProductRevenue(productId));
}

次の例で、コレクション (IQueryable オブジェクトとして) を返すモデル定義関数を呼び出す方法を説明します。 指定された製品 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>

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

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
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))));
    }
}

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

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
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);
    }
}

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

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

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

SalesOrderDetail コレクションの製品収益を返す下の概念モデル関数について考察してください (関数を概念モデルに追加する方法については、「How to: Define Custom Functions in the Conceptual Model」を参照してください)。

<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>

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

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
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>))));
    }
}

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

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
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));
}

参照

概念

LINQ to Entities でのクエリ
LINQ to Entities クエリ内の関数の呼び出し

その他のリソース

.edmx File Overview