Dela via


Anvisningar: Anropa modelldefinierade funktioner som objektmetoder

Det här avsnittet beskriver hur du anropar en modelldefinierad funktion som en metod för ett ObjectContext objekt eller som en statisk metod i en anpassad klass. En modelldefinierad funktion är en funktion som definieras i den konceptuella modellen. Procedurerna i avsnittet beskriver hur du anropar dessa funktioner direkt i stället för att anropa dem från LINQ till entitetsfrågor. Information om hur du anropar modelldefinierade funktioner i LINQ till entitetsfrågor finns i Så här anropar du modelldefinierade funktioner i frågor.

Oavsett om du anropar en modelldefinierad funktion som en ObjectContext metod eller som en statisk metod i en anpassad klass måste du först mappa metoden till den modelldefinierade funktionen med en EdmFunctionAttribute. Men när du definierar en metod för ObjectContext klassen måste du använda QueryProvider egenskapen för att exponera LINQ-providern, medan du måste använda Provider egenskapen för att exponera LINQ-providern när du definierar en statisk metod för en anpassad klass. Mer information finns i exemplen som följer procedurerna nedan.

Procedurerna nedan innehåller dispositioner på hög nivå för att anropa en modelldefinierad funktion som en metod för ett ObjectContext objekt och som en statisk metod i en anpassad klass. Exemplen som följer ger mer information om stegen i procedurerna. Procedurerna förutsätter att du har definierat en funktion i konceptmodellen. Mer information finns i Så här: Definiera anpassade funktioner i konceptmodellen.

Anropa en modelldefinierad funktion som en metod för ett ObjectContext-objekt

  1. Lägg till en källfil för att utöka den partiella klassen som härletts från ObjectContext klassen, som genereras automatiskt av Entity Framework-verktygen. Om du definierar CLR-stub i en separat källfil förhindras ändringarna från att gå förlorade när filen återskapas.

  2. Lägg till en CLR-metod (Common Language Runtime) i klassen ObjectContext som gör följande:

    • Kartor till funktionen som definierats i den konceptuella modellen. Om du vill mappa metoden måste du använda en EdmFunctionAttribute för -metoden. Observera att parametrarna NamespaceName och FunctionName för attributet är namnområdesnamnet för den konceptuella modellen respektive funktionsnamnet i den konceptuella modellen. Funktionsnamnmatchning för LINQ är skiftlägeskänslig.

    • Returnerar resultatet av den Execute metod som returneras av QueryProvider egenskapen.

  3. Anropa metoden som medlem på en instans av ObjectContext klassen.

Anropa en modelldefinierad funktion som statisk metod i en anpassad klass

  1. Lägg till en klass i ditt program med en statisk metod som gör följande:

    • Kartor till funktionen som definierats i den konceptuella modellen. Om du vill mappa metoden måste du använda en EdmFunctionAttribute för -metoden. Observera att parametrarna NamespaceName och FunctionName för attributet är namnområdesnamnet för den konceptuella modellen respektive funktionsnamnet i den konceptuella modellen.

    • Accepterar ett IQueryable argument.

    • Returnerar resultatet av den Execute metod som returneras av Provider egenskapen.

  2. Anropa metoden som medlem för en statisk metod i den anpassade klassen

Exempel 1

Anropa en modelldefinierad funktion som en metod för ett ObjectContext-objekt

I följande exempel visas hur du anropar en modelldefinierad funktion som en metod för ett ObjectContext objekt. I exemplet används AdventureWorks-försäljningsmodellen.

Överväg den konceptuella modellfunktionen nedan som returnerar produktintäkter för en angiven produkt. (Information om hur du lägger till funktionen i din konceptuella modell finns i Gör så här: Definiera anpassade funktioner i konceptmodellen.)

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

Exempel 2

Följande kod lägger till en metod i klassen AdventureWorksEntities som mappar till den konceptuella modellfunktionen ovan.

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

Exempel 3

Följande kod anropar metoden ovan för att visa produktintäkterna för en angiven produkt:

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

Exempel 4

I följande exempel visas hur du anropar en modelldefinierad funktion som returnerar en samling (som ett IQueryable<T> objekt). Överväg den konceptuella modellfunktionen nedan som returnerar alla SalesOrderDetails för ett visst produkt-ID.

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

Exempel 5

Följande kod lägger till en metod i klassen AdventureWorksEntities som mappar till den konceptuella modellfunktionen ovan.

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

Exempel 6

Följande kod anropar metoden. Observera att den returnerade frågan förfinas IQueryable<T> ytterligare för att returnera radsummor för varje 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

Exempel 7

Anropa en modelldefinierad funktion som en statisk metod i en anpassad klass

I nästa exempel visas hur du anropar en modelldefinierad funktion som en statisk metod i en anpassad klass. I exemplet används AdventureWorks-försäljningsmodellen.

Kommentar

När du anropar en modelldefinierad funktion som en statisk metod i en anpassad klass måste den modelldefinierade funktionen acceptera en samling och returnera en sammansättning av värden i samlingen.

Överväg den konceptuella modellfunktionen nedan som returnerar produktintäkter för en SalesOrderDetail-samling. (Information om hur du lägger till funktionen i din konceptuella modell finns i Gör så här: Definiera anpassade funktioner i konceptmodellen.)

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

Exempel 8

Följande kod lägger till en klass i ditt program som innehåller en statisk metod som mappar till den konceptuella modellfunktionen ovan.

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

Exempel 9

Följande kod anropar metoden ovan för att visa produktintäkterna för en SalesOrderDetail-samling:

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

Se även