共用方式為


如何:將模型定義函式當做物件方法來呼叫

本主題描述如何呼叫模型定義函式做為 ObjectContext 物件上的方法,或做為自訂類別上的靜態方法。 「模型定義函式」是概念模型中定義的函式。 本主題的程序說明如何直接呼叫這些函式,而不是從 LINQ to Entities 查詢呼叫函式。 如需在 LINQ to Entities 查詢中呼叫模型定義函式的相關資訊,請參閱作法:在查詢中呼叫模型定義函式

無論您是呼叫模型定義函式做為 ObjectContext 方法,或是做為自訂類別上的靜態方法,您必須先使用 EdmFunctionAttribute 將方法對應至模型定義函式。 不過,當您定義 ObjectContext 類別上的方法時,您必須使用 QueryProvider 屬性公開 LINQ 提供者,而當您定義自訂類別上的靜態方法時,您必須使用 Provider 屬性公開 LINQ 提供者。 如需詳細資訊,請參閱下列程序後的範例。

以下程序提供的重要概述,是關於呼叫模型定義函式做為 ObjectContext 物件上的方法,以及呼叫做為自訂類別上的靜態方法。 下面的範例提供更多關於程序中之步驟的詳細資訊。 程序假設您已在概念模型中定義函式。 如需詳細資訊,請參閱作法:在概念模型中定義自訂函式

呼叫模型定義函式做為 ObjectContext 物件上的方法

  1. 加入來源檔案以擴充衍生自 ObjectContext 類別的部分類別,該類別由 Entity Framework 工具自動產生。 在另外的來源檔案中定義 CLR stub,可在檔案重新產生時,防止遺失變更的問題。

  2. 將 Common Language Runtime (CLR) 方法加入至執行下列工作的 ObjectContext 類別:

    • 對應至概念模型中定義的函式。 若要對應方法,您必須將 EdmFunctionAttribute 套用至方法。 請注意,屬性的 NamespaceNameFunctionName 參數分別是概念模型的命名空間名稱和概念模型中的函式名稱。 LINQ 的函式名稱解析是區分大小寫的。

    • Execute 屬性傳回的方法會傳回 QueryProvider 的結果。

  3. 呼叫方法做為 ObjectContext 類別之執行個體上的成員。

呼叫模型定義函式做為自訂類別上的靜態方法

  1. 使用執行下列工作的靜態方法,將類別加入至您的應用程式:

  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

注意

當您呼叫模型定義函式做為自訂類別上的靜態方法時,模型定義函式必須接受集合,並傳回集合中之值的彙總。

考慮以下傳回 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

另請參閱