Condividi tramite


Procedura: chiamare funzioni definite dal modello come metodi di oggetto (LINQ to Entities)

In questo argomento viene descritto come chiamare una funzione definita dal modello come metodo in un oggetto ObjectContext oppure come metodo statico di una classe personalizzata. Una funzione definita dal modello è una funzione che è definita nel modello concettuale. Le procedure descritte in questo argomento mostrano come chiamare queste funzioni direttamente anziché chiamarle da query LINQ to Entities. Per informazioni sulla chiamata di funzioni definite dal modello tramite query LINQ to Entities, vedere Procedura: chiamare funzioni definite dal modello nelle query (LINQ to Entities).

Sia che si chiami una funzione definita dal modello come metodo ObjectContext o come metodo statico in una classe personalizzata, è necessario innanzitutto eseguire il mapping del metodo alla funzione definita dal modello con un oggetto EdmFunctionAttribute. Tuttavia, quando si definisce un metodo nella classe ObjectContext, è necessario utilizzare la proprietà QueryProvider per esporre il provider LINQ, mentre quando si definisce un metodo statico in una classe personalizzata, è necessario utilizzare la proprietà Provider per esporre il provider LINQ. Per ulteriori informazioni, vedere gli esempi che seguono le procedure.

Le procedure descritte di seguito forniscono strutture di alto livello per la chiamata di una funzione definita dal modello come metodo in un oggetto ObjectContext e come metodo statico in una classe personalizzata. Negli esempi che seguono vengono forniti dettagli aggiuntivi sui passaggi delle procedure. In queste procedure si presuppone che sia stata definita una funzione nel modello concettuale. Per ulteriori informazioni, vedere How to: Define Custom Functions in the Conceptual Model.

Per chiamare una funzione definita dal modello come metodo in un oggetto ObjectContext

  1. Aggiungere un file di origine per estendere la classe parziale derivata dalla classe ObjectContext, generata automaticamente dagli strumenti di Entity Framework. La definizione dello stub CLR in un file di origine separato impedirà la perdita delle modifiche durante la rigenerazione del file.

  2. Aggiungere un metodo Common Language Runtime (CLR) alla classe ObjectContext che:

    • Esegue il mapping alla funzione definita nel modello concettuale. Per eseguire il mapping del metodo, è necessario applicare un oggetto EdmFunctionAttribute al metodo. Si noti che i parametri NamespaceName e FunctionName dell'attributo sono rispettivamente il nome dello spazio dei nomi del modello concettuale e il nome della funzione nel modello concettuale. La risoluzione del nome della funzione per LINQ rileva la distinzione tra maiuscole e minuscole.

    • Restituisce i risultati del metodo Execute che viene restituito dalla proprietà QueryProvider.

  3. Chiamare il metodo come membro di un'istanza della classe ObjectContext.

Per chiamare una funzione definita dal modello come metodo statico in una classe personalizzata

  1. Aggiungere una classe all'applicazione con un metodo statico che:

    • Esegue il mapping alla funzione definita nel modello concettuale. Per eseguire il mapping del metodo, è necessario applicare un oggetto EdmFunctionAttribute al metodo. Si noti che i parametri NamespaceName e FunctionName dell'attributo sono rispettivamente il nome dello spazio dei nomi del modello concettuale e il nome della funzione nel modello concettuale.

    • Accetta un argomento IQueryable.

    • Restituisce i risultati del metodo Execute che viene restituito dalla proprietà Provider.

  2. Chiamare il metodo come membro di un metodo statico nella classe personalizzata

Esempio

Chiamata di una funzione definita dal modello come metodo in un oggetto ObjectContext

Nell'esempio seguente viene mostrato come chiamare una funzione definita dal modello come metodo in un oggetto ObjectContext. Nell'esempio viene utilizzato il Modello Sales di AdventureWorks.

Considerare la seguente funzione del modello concettuale che restituisce il ricavo di prodotto per un prodotto specificato. Per informazioni sull'aggiunta della funzione al modello concettuale, vedere 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>

Nel codice seguente viene aggiunto un metodo alla classe AdventureWorksEntities che esegue il mapping alla suddetta funzione del modello concettuale.

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

Nel codice seguente viene chiamato il metodo sopraindicato per visualizzare il ricavo di prodotto per un prodotto specificato:

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

Nell'esempio seguente viene mostrato come chiamare una funzione definita dal modello che restituisce una raccolta (come un oggetto IQueryable). Considerare la seguente funzione del modello concettuale che restituisce tutti i SalesOrderDetails per un dato ID di prodotto.

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

Nel codice seguente viene aggiunto un metodo alla classe AdventureWorksEntities che esegue il mapping alla suddetta funzione del modello concettuale.

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

Nell'esempio di codice riportato di seguito viene chiamato il metodo. Si noti che la query IQueryable restituita è ridefinita ulteriormente in modo da restituire i totali delle righe per ogni 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);
    }
}

Chiamata di una funzione definita dal modello come metodo statico in una classe personalizzata

Nell'esempio seguente viene dimostrato come chiamare una funzione definita dal modello come metodo statico in una classe personalizzata. Nell'esempio viene utilizzato il Modello Sales di AdventureWorks.

Dd456845.note(it-it,VS.100).gifNota:
Quando si chiama una funzione definita dal modello come metodo statico in una classe personalizzata, la funzione definita dal modello deve accettare una raccolta e restituire un'aggregazione di valori nella raccolta.

Considerare la seguente funzione del modello concettuale che restituisce il ricavo di prodotto per una raccolta SalesOrderDetail. Per informazioni sull'aggiunta della funzione al modello concettuale, vedere 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>

Nel codice seguente viene aggiunta una classe all'applicazione contenente un metodo statico che esegue il mapping alla suddetta funzione del modello concettuale.

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

Nel codice seguente viene chiamato il metodo sopraindicato per visualizzare il ricavo di prodotto per una raccolta 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));
}

Vedere anche

Concetti

Query in LINQ to Entities
Chiamata di funzioni nelle query LINQ to Entities

Altre risorse

.edmx File Overview