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 物件上的方法
加入來源檔案以擴充衍生自 ObjectContext 類別的部分類別,該類別由 Entity Framework 工具自動產生。 在另外的來源檔案中定義 CLR stub,可在檔案重新產生時,防止遺失變更的問題。
將 Common Language Runtime (CLR) 方法加入至執行下列工作的 ObjectContext 類別:
對應至概念模型中定義的函式。 若要對應函式,您必須將 EdmFunctionAttribute 套用至方法。 請注意,屬性的 NamespaceName 和 FunctionName 參數分別是概念模型的命名空間名稱和概念模型中的函式名稱。 LINQ 的函式名稱解析是區分大小寫的。
由 QueryProvider 屬性傳回的方法會傳回 Execute 的結果。
呼叫方法做為 ObjectContext 類別之執行個體上的成員。
呼叫模型定義函式做為自訂類別上的靜態方法
使用執行下列工作的靜態方法,將類別加入至您的應用程式:
對應至概念模型中定義的函式。 若要對應函式,您必須將 EdmFunctionAttribute 套用至方法。 請注意,屬性的 NamespaceName 和 FunctionName 參數分別是概念模型的命名空間名稱和概念模型中的函式名稱。
接受 IQueryable 引數。
由 Provider 屬性傳回的方法會傳回 Execute 的結果。
呼叫方法做為自訂類別上之靜態方法的成員
範例
呼叫模型定義函式做為 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。
注意: |
---|
當您呼叫模型定義函式做為自訂類別上的靜態方法時,模型定義函式必須接受集合,並傳回集合中之值的彙總。 |
考慮以下傳回 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 查詢中的函式