Vorgehensweise: Aufrufen modelldefinierter Funktionen als Objektmethoden

In diesem Thema wird beschrieben, wie eine modelldefinierte Funktion als Methode für ein ObjectContext-Objekt oder als statische Methode für eine benutzerdefinierte Klasse aufgerufen wird. Eine modelldefinierte Funktion ist eine Funktion, die im konzeptionellen Modell definiert wird. Die folgenden Prozeduren beschreiben, wie diese Funktionen direkt aufgerufen werden, anstatt sie von LINQ to Entities-Abfragen aufzurufen. Informationen zum Aufrufen modelldefinierter Funktionen in LINQ to Entities-Abfragen finden Sie unter Gewusst wie: Aufrufen modelldefinierter Funktionen in Abfragen.

Egal, ob Sie eine modelldefinierte Funktion als ObjectContext-Methode oder statische Methode für eine benutzerdefinierte Klasse aufrufen: Zuerst muss die Methode der modelldefinierten Funktion mit einem EdmFunctionAttribute zugeordnet werden. Wenn Sie jedoch für die ObjectContext-Klasse eine Methode definieren, müssen Sie den LINQ-Anbieter mithilfe der QueryProvider-Eigenschaft bereitstellen. Wenn Sie jedoch für eine benutzerdefinierte Klasse eine statische Methode definieren, müssen Sie den LINQ-Anbieter mithilfe der Provider-Eigenschaft bereitstellen. Weitere Informationen finden Sie in den Beispielen im Anschluss an die folgenden Prozeduren.

Die folgenden Prozeduren stellen in knapper Form dar, wie eine modelldefinierte Funktion als Methode für ein ObjectContext-Objekt und als statische Methode für eine benutzerdefinierte Klasse aufgerufen wird. Die folgenden Beispiele enthalten weitere Details zu den Schritten in den Prozeduren. In den Prozeduren wird davon ausgegangen, dass eine Funktion im konzeptionellen Modell definiert wurde. Weitere Informationen finden Sie unter Gewusst wie: Definieren benutzerdefinierter Funktionen im konzeptionellen Modell.

So rufen Sie eine modelldefinierte Funktion als Methode für ein ObjectContext-Objekt auf

  1. Fügen Sie eine Quelldatei hinzu, um die partielle von den Entity Framework-Tools generierte und von der ObjectContext Klasse abgeleitete Klasse zu erweitern. Durch die Definition des CLR-Stub in einer separaten Quelldatei werden die Änderungen bei der erneuten Erstellung der Datei beibehalten.

  2. Fügen Sie der ObjectContext-Klasse, die wie folgt vorgeht, eine Common Language Runtime (CLR)-Methode hinzu:

    • Sie ordnet der im konzeptionellen Modell definierten Funktion Objekte zu. Zum Zuordnen der Methode müssen Sie ein EdmFunctionAttribute für die Methode übernehmen. Beachten Sie, dass der NamespaceName-Parameter und der FunctionName-Parameter des Attributs im konzeptionellen Modell den Namespacenamen und den Funktionsnamen darstellen. Bei der Funktionsnamenauflösung für LINQ wird die Groß-/Kleinschreibung berücksichtigt.

    • Gibt die Ergebnisse der Execute-Methode zurück, die von der QueryProvider-Eigenschaft zurückgegeben werden.

  3. Rufen Sie die statische Methode als ein Member für eine Instanz der ObjectContext-Klasse auf.

So rufen Sie eine modelldefinierte Funktion als statische Methode für eine benutzerdefinierte Klasse auf

  1. Fügen Sie der Anwendung eine Klasse mit einer statischen Methode hinzu, die wie folgt vorgeht:

    • Sie ordnet der im konzeptionellen Modell definierten Funktion Objekte zu. Zum Zuordnen der Methode müssen Sie ein EdmFunctionAttribute für die Methode übernehmen. Beachten Sie, dass der NamespaceName-Parameter und der FunctionName-Parameter des Attributs im konzeptionellen Modell den Namespacenamen und den Funktionsnamen darstellen.

    • Akzeptiert ein IQueryable-Argument.

    • Gibt die Ergebnisse der Execute-Methode zurück, die von der Provider-Eigenschaft zurückgegeben werden.

  2. Aufrufen der Methode als Member einer statischen Methode für die benutzerdefinierte Klasse

Beispiel 1

Aufrufen einer modelldefinierten Funktion als Methode für ein ObjectContext-Objekt

Im folgenden Beispiel wird veranschaulicht, wie eine modelldefinierte Funktion als Methode für ein ObjectContext-Objekt aufgerufen wird. Im Beispiel wird das AdventureWorks Sales-Modell verwendet.

Erwägen Sie die Verwendung der folgenden konzeptionellen Modellfunktion, die Produkteinnahmen für ein angegebenes Produkt zurückgibt. (Informationen zum Hinzufügen der Funktion zu Ihrem konzeptionellen Modell finden Sie unter Gewusst wie: Definieren benutzerdefinierter Funktionen im konzeptionellen Modell.)

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

Beispiel 2

Mit dem folgenden Code wird der AdventureWorksEntities-Klasse eine Methode hinzugefügt, die der konzeptionellen Modellfunktion oben zugeordnet wird.

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

Beispiel 3

Im folgenden Code wird die Methode oben aufgerufen, um die Produkteinnahmen oben für ein angegebenes Produkt anzuzeigen:

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

Beispiel 4

Im folgenden Beispiel wird veranschaulicht, wie eine modelldefinierte Funktion, die eine Auflistung (als IQueryable<T>-Objekt) zurückgibt, aufgerufen wird. Erwägen Sie den Einsatz der folgenden konzeptionellen Modellfunktion, die alle SalesOrderDetails für eine angegebene Produkt-ID zurückgibt.

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

Beispiel 5

Mit dem folgenden Code wird der AdventureWorksEntities-Klasse eine Methode hinzugefügt, die der konzeptionellen Modellfunktion oben zugeordnet wird.

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

Beispiel 6

Der folgende Code ruft die Methode auf. Beachten Sie, dass die zurückgegebene IQueryable<T>-Abfrage weiter verfeinert wird, um für jedes SalesOrderDetail Zeilengesamtbeträge zurückzugeben.

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

Beispiel 7

Aufrufen einer modelldefinierten Funktion als statische Methode für eine benutzerdefinierte Klasse

Im nächsten Beispiel wird veranschaulicht, wie eine modelldefinierte Funktion als statische Methode für eine benutzerdefinierte Klasse aufgerufen wird. Im Beispiel wird das AdventureWorks Sales-Modell verwendet.

Hinweis

Wenn Sie eine modelldefinierte Funktion als statische Methode für eine benutzerdefinierte Klasse aufrufen, muss die modelldefinierte Funktion eine Auflistung akzeptieren und eine Aggregation von Werten in der Auflistung zurückgeben.

Erwägen Sie die Verwendung der folgenden konzeptionellen Modellfunktion, die Produkteinnahmen für eine SalesOrderDetail-Auflistung zurückgibt. (Informationen zum Hinzufügen der Funktion zu Ihrem konzeptionellen Modell finden Sie unter Gewusst wie: Definieren benutzerdefinierter Funktionen im konzeptionellen Modell.)

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

Beispiel 8

Der folgende Code fügt der Anwendung eine Klasse hinzu, die eine statische Methode enthält, die der konzeptionellen Modellfunktion oben zugeordnet wird.

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

Beispiel 9

Der folgenden Code ruft die Methode oben auf, um die Produkteinnahmen für eine SalesOrderDetail-Auflistung anzuzeigen:

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

Siehe auch