Cómo llamar a funciones definidas por el modelo como métodos de objeto

En este tema se describe cómo llamar a una función definida por el modelo como un método en un ObjectContext objeto o como un método estático en una clase personalizada. Una función definida por el modelo es una función definida en el modelo conceptual. Los procedimientos de este tema describen cómo llamar a estas funciones directamente en lugar de hacerlo desde las consultas de LINQ to Entities. Para obtener información sobre cómo llamar a funciones definidas por el modelo en consultas LINQ to Entities, vea How to: Call Model-Defined Functions in Queries.

Tanto si llama a una función definida por el modelo mediante un método ObjectContext o un método estático en una clase personalizada, primero debe asignar el método a la función definida por el modelo con un EdmFunctionAttribute. Sin embargo, al definir un método en la ObjectContext clase , debe usar la QueryProvider propiedad para exponer el proveedor LINQ, mientras que al definir un método estático en una clase personalizada, debe usar la Provider propiedad para exponer el proveedor LINQ. Para obtener más información, vea los ejemplos que siguen los procedimientos siguientes.

Los procedimientos siguientes proporcionan esquemas generales para llamar a una función definida por el modelo como un método en un ObjectContext objeto y como un método estático en una clase personalizada. Los ejemplos siguientes proporcionan más detalles sobre los pasos descritos en los procedimientos. Los procedimientos suponen que ha definido una función en el modelo conceptual. Para obtener más información, vea Cómo: Definir funciones personalizadas en el modelo conceptual.

Para llamar a una función definida por el modelo como método en un objeto ObjectContext

  1. Agregue un archivo de origen para ampliar la clase parcial derivada de la ObjectContext clase generada automáticamente por las herramientas de Entity Framework. Definir el código auxiliar CLR en un archivo de origen independiente impedirá que se pierdan los cambios cuando se vuelva a generar el archivo.

  2. Agregue un método de Common Language Runtime (CLR) a la ObjectContext clase que haga lo siguiente:

    • Corresponde a la función definida en el modelo conceptual. Para mapear el método, debe aplicar un EdmFunctionAttribute al método. Tenga en cuenta que los parámetros NamespaceName y FunctionName del atributo corresponden al nombre del espacio de nombres del modelo conceptual y al nombre de la función en el modelo conceptual, respectivamente. La resolución de nombres de función para LINQ distingue mayúsculas de minúsculas.

    • Devuelve los resultados del Execute método devuelto por la QueryProvider propiedad .

  3. Llame al método como miembro en una instancia de la clase ObjectContext.

Para llamar a una función definida por el modelo como método estático en una clase personalizada

  1. Agregue una clase a la aplicación con un método estático que haga lo siguiente:

    • Corresponde a la función definida en el modelo conceptual. Para mapear el método, debe aplicar un EdmFunctionAttribute al método. Tenga en cuenta que los parámetros NamespaceName y FunctionName del atributo son, respectivamente, el nombre del espacio de nombres del modelo conceptual y el nombre de la función en el modelo conceptual.

    • Acepta un IQueryable argumento.

    • Devuelve los resultados del Execute método devuelto por la Provider propiedad .

  2. Llame al método como miembro de un método estático en la clase personalizada.

Ejemplo 1

Llamar a una función de Model-Defined como método en un objeto ObjectContext

En el ejemplo siguiente se muestra cómo llamar a una función definida por el modelo como un método en un ObjectContext objeto . En el ejemplo se usa el modelo de ventas de AdventureWorks.

Tenga en cuenta la función del modelo conceptual siguiente que devuelve los ingresos del producto para un producto especificado. (Para obtener información sobre cómo agregar la función al modelo conceptual, vea 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>

Ejemplo 2

El código siguiente agrega un método a la clase AdventureWorksEntities que mapea a la función del modelo conceptual anterior.

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

Ejemplo 3

El código siguiente llama al método anterior para mostrar los ingresos del producto para un producto 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

Ejemplo 4

En el ejemplo siguiente se muestra cómo llamar a una función definida por el modelo que devuelve una colección (como un IQueryable<T> objeto). Considere la función de modelo conceptual siguiente que devuelve todos los SalesOrderDetails para un identificador de producto determinado.

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

Ejemplo 5

El código siguiente agrega un método a la clase AdventureWorksEntities que se asigna a la función del modelo conceptual anterior.

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

Ejemplo 6

El código siguiente llama al método . Tenga en cuenta que la consulta devuelta IQueryable<T> se afina aún más para devolver el total de línea 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

Ejemplo 7

Llamar a una función Model-Defined como método estático en una clase personalizada

En el ejemplo siguiente se muestra cómo llamar a una función definida por el modelo como un método estático en una clase personalizada. En el ejemplo se usa el modelo de ventas de AdventureWorks.

Nota:

Cuando se llama a una función definida por el modelo como un método estático en una clase personalizada, la función definida por el modelo debe aceptar una colección y devolver una agregación de valores en la colección.

Tenga en cuenta la función de modelo conceptual siguiente que devuelve los ingresos del producto para una colección SalesOrderDetail. (Para obtener información sobre cómo agregar la función al modelo conceptual, vea 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>

Ejemplo 8

El código siguiente agrega una clase a la aplicación que contiene un método estático que se asigna a la función del modelo conceptual anterior.

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

Ejemplo 9

El código siguiente llama al método anterior para mostrar los ingresos del producto para una colección 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 también