Share via


Gewusst wie: Aufrufen von modelldefinierten Funktionen als Objektmethoden (LINQ to Entities)

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 von modelldefinierten Funktionen in LINQ to Entities-Abfragen finden Sie unter Gewusst wie: Aufrufen von im Modell definierten Funktionen in Abfragen (LINQ to Entities).

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 How to: Define Custom Functions in the Conceptual Model.

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

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 zum konzeptionellen Modell finden Sie unter 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>

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

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

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

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

Im folgenden Beispiel wird veranschaulicht, wie eine modelldefinierte Funktion, die eine Auflistung (als IQueryable-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>

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

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

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

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

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.

Dd456845.note(de-de,VS.100).gifHinweis:
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 zum konzeptionellen Modell finden Sie unter 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>

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

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

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

Siehe auch

Konzepte

Abfragen in LINQ to Entities
Aufrufen von Funktionen in LINQ to Entities-Abfragen

Weitere Ressourcen

.edmx File Overview