共用方式為


HOW TO:呼叫模型定義函式做為物件方法 (LINQ to Entities)

本主題描述如何呼叫模型定義函式做為 ObjectContext 物件上的方法,或做為自訂類別上的靜態方法。 「模型定義函式」(Model-defined Function) 是概念模型中定義的函式。 本主題的程序說明如何直接呼叫這些函式,而不是從 LINQ to Entities 查詢呼叫函式。 如需關於在 LINQ to Entities 查詢中呼叫模型定義函式的詳細資訊,請參閱 HOW TO:在查詢中呼叫模型定義函式 (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 stub,可在檔案重新產生時,防止遺失變更的問題。

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

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

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

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

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

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

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

    • 接受 IQueryable 引數。

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

  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(zh-tw,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