Como Chamar Funções Definidas por Modelo como Métodos de Objeto

Este tópico descreve como chamar uma função definida pelo modelo como um método num ObjectContext objeto ou como um método estático numa classe personalizada. Uma função definida pelo modelo é uma função definida no modelo conceptual. Os procedimentos neste tópico descrevem como chamar estas funções diretamente em vez de as chamar de consultas LINQ to Entities. Para obter informações sobre como chamar funções definidas pelo modelo em consultas LINQ para Entidades, consulte o tópico Como: Chamar Funções Definidas pelo Modelo em Consultas.

Quer chame uma função definida por modelo como método ObjectContext ou como método estático numa classe personalizada, deve primeiro mapear o método para a função definida pelo modelo com um EdmFunctionAttribute. No entanto, quando defines um método na ObjectContext classe, deves usar a QueryProvider propriedade para expor o fornecedor LINQ, enquanto quando defines um método estático numa classe personalizada, deves usar a Provider propriedade para expor o fornecedor LINQ. Para mais informações, consulte os exemplos que seguem os procedimentos abaixo.

Os procedimentos abaixo fornecem esboços de alto nível para chamar uma função definida por modelo como um método num ObjectContext objeto e como um método estático numa classe personalizada. Os exemplos que se seguem fornecem mais detalhes sobre os passos dos procedimentos. Os procedimentos assumem que definiu uma função no modelo conceptual. Para mais informações, veja Como: Definir Funções Personalizadas no Modelo Conceptual.

Chamar uma função definida pelo modelo como um método num objeto ObjectContext

  1. Adicione um ficheiro fonte para estender a classe parcial derivada da ObjectContext classe, gerada automaticamente pelas ferramentas Entity Framework. Definir o stub CLR num ficheiro fonte separado evitará que as alterações se percam quando o ficheiro for regenerado.

  2. Adicione um método de tempo de execução de linguagem comum (CLR) à sua ObjectContext classe para fazer o seguinte:

    • Mapeia para a função definida no modelo conceptual. Para mapear o método, deve aplicar uma EdmFunctionAttribute ao método. Note-se que os parâmetros NamespaceName e FunctionName do atributo são, respetivamente, o nome do espaço de nomes e o nome da função no modelo conceptual. A resolução do nome da função para o LINQ é sensível a maiúsculas e minúsculas.

    • Retorna os resultados do método Execute que é retornado pela propriedade QueryProvider.

  3. Chame o método como membro numa instância da ObjectContext classe.

Chamar uma função definida pelo modelo como método estático numa classe personalizada

  1. Adicione uma classe à sua aplicação com um método estático que faça o seguinte:

    • Mapeia para a função definida no modelo conceptual. Para mapear o método, deve aplicar EdmFunctionAttribute ao método. Note-se que os parâmetros NamespaceName e FunctionName do atributo são, respetivamente, o nome do espaço de nomes do modelo conceptual e o nome da função no modelo conceptual.

    • Aceita um IQueryable argumento.

    • Devolve os resultados do método Execute que é retornado pela propriedade Provider.

  2. Chame o método como se fosse um membro de um método estático na classe personalizada.

Exemplo 1

Chamar uma função Model-Defined como método num objeto ObjectContext

O exemplo seguinte demonstra como chamar uma função definida pelo modelo como um método num ObjectContext objeto. O exemplo utiliza o Modelo de Vendas AdventureWorks.

Considere a função do modelo conceptual abaixo que retorna a receita do produto para um produto especificado. (Para informações sobre como adicionar a função ao seu modelo conceptual, veja Como: Definir Funções Personalizadas no Modelo Conceptual.)

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

Exemplo 2

O código seguinte adiciona um método à AdventureWorksEntities classe que corresponde à função modelo conceptual acima.

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

Exemplo 3

O seguinte código chama o método acima para mostrar a receita do produto para um produto especificado:

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

Exemplo 4

O exemplo seguinte demonstra como chamar uma função definida pelo modelo que devolve uma coleção (como um IQueryable<T> objeto). Considere a função modelo conceptual abaixo que devolve todos os SalesOrderDetails para um determinado ID de produto.

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

Exemplo 5

O código seguinte adiciona um método à AdventureWorksEntities classe que corresponde à função modelo conceptual acima.

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

Exemplo 6

O código seguinte chama o método. Note que a consulta devolvida IQueryable<T> é ainda mais refinada para devolver os totais de linhas para cada 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

Exemplo 7

Chamar uma função Model-Defined como um método estático numa classe personalizada

O exemplo seguinte demonstra como chamar uma função definida pelo modelo como um método estático numa classe personalizada. O exemplo utiliza o Modelo de Vendas AdventureWorks.

Observação

Quando chama uma função definida pelo modelo como método estático numa classe personalizada, a função definida pelo modelo deve aceitar uma coleção e devolver uma agregação de valores na coleção.

Considere a função do modelo conceptual abaixo que devolve receitas de produto para uma coleção SalesOrderDetail. (Para informações sobre como adicionar a função ao seu modelo conceptual, veja Como: Definir Funções Personalizadas no Modelo Conceptual.)

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

Exemplo 8

O código seguinte adiciona uma classe à sua aplicação que contém um método estático que corresponde à função do modelo conceptual acima.

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

Exemplo 9

O código seguinte chama o método acima para mostrar a receita do produto para uma coleção 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

Consulte também