Procedura: chiamare funzioni definite dal modello come metodi di oggetto
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 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 nelle query LINQ to Entities, vedere Procedura: Chiamare funzioni definite dal modello in query.
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 usare la proprietà QueryProvider per esporre il provider LINQ, mentre quando si definisce un metodo statico in una classe personalizzata, è necessario usare la proprietà Provider per esporre il provider LINQ. Per altre 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 altre informazioni, vedere Procedura: Definire funzioni personalizzate nel modello concettuale.
Per chiamare una funzione definita dal modello come metodo in un oggetto ObjectContext
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.
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.
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
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.
Chiamare il metodo come membro di un metodo statico nella classe personalizzata
Esempio 1
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 usato 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 a un modello concettuale, vedere Procedura: Definire funzioni personalizzate nel modello concettuale.
<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>
Esempio 2
Nel codice seguente viene aggiunto un metodo alla classe AdventureWorksEntities
che esegue il mapping alla suddetta funzione del modello concettuale.
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
Esempio 3
Nel codice seguente viene chiamato il metodo sopraindicato per visualizzare il ricavo di prodotto per un prodotto specificato:
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
Esempio 4
Nell'esempio seguente viene mostrato come chiamare una funzione definita dal modello che restituisce una raccolta (come un oggetto IQueryable<T>). 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>
Esempio 5
Nel codice seguente viene aggiunto un metodo alla classe AdventureWorksEntities
che esegue il mapping alla suddetta funzione del modello concettuale.
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
Esempio 6
Nell'esempio di codice riportato di seguito viene chiamato il metodo. Si noti che la query IQueryable<T> restituita è ridefinita ulteriormente in modo da restituire i totali delle righe per ogni 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
Esempio 7
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 usato il Modello Sales di AdventureWorks.
Nota
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 a un modello concettuale, vedere Procedura: Definire funzioni personalizzate nel modello concettuale.
<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>
Esempio 8
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 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
Esempio 9
Nel codice seguente viene chiamato il metodo sopraindicato per visualizzare il ricavo di prodotto per una raccolta SalesOrderDetail:
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