Procédure : personnaliser des objets de données générés (Entity Framework)

Cette rubrique montre comment ajouter une méthode personnalisée à une classe de données générée. Les exemples de cette rubrique sont basés sur le modèle de vente Adventure Works Sales Model. Pour exécuter le code de cet exemple, vous devez déjà avoir ajouté le modèle de vente AdventureWorks Sales Model à votre projet et configuré ce dernier pour qu'il utilise Entity Framework. Pour cela, exécutez les procédures décrites dans Procédure : configurer manuellement un projet Entity Framework et Procédure : définir manuellement un modèle EDM (Entity Data Model) (Entity Framework).

Exemple

Cet exemple définit une méthode UpdateOrderTotal personnalisée pour la classe SalesOrderHeader générée. Cette méthode personnalisée met à jour la propriété TotalDue en fonction des valeurs actuelles des taxes, frais de transports et totaux des articles individuels. Cette méthode est définie comme une classe partielle de manière à qu'elle ne soit pas supprimée lorsque la classe SalesOrderHeader est régénérée par les outils Entity Framework.

Partial Public Class SalesOrderHeader
    ' Update the order total.
    Public Sub UpdateOrderTotal()

        Dim newSubTotal As Decimal = 0

        ' Ideally, this information is available in the EDM.
        Dim taxRatePercent As Decimal = GetCurrentTaxRate()
        Dim freightPercent As Decimal = GetCurrentFreight()

        ' If the items for this order are loaded or if the order is 
        ' newly added, then recalculate the subtotal as it may have changed.
        If (Me.SalesOrderDetail.IsLoaded Or _
            Me.EntityState = Data.EntityState.Added) Then

            Dim item As SalesOrderDetail
            For Each item In Me.SalesOrderDetail
                ' Calculate line totals for loaded items.
                newSubTotal += (item.OrderQty * _
                    (item.UnitPrice - item.UnitPriceDiscount))
            Next
            Me.SubTotal = newSubTotal
        End If

        ' Calculate the new tax amount.
        Me.TaxAmt = Me.SubTotal _
             + Decimal.Round((Me.SubTotal * taxRatePercent / 100), 4)

        ' Calculate the new freight amount.
        Me.Freight = Me.SubTotal _
            + Decimal.Round((Me.SubTotal * freightPercent / 100), 4)

        ' Calculate the new total.
        Me.TotalDue = Me.SubTotal + Me.TaxAmt + Me.Freight

    End Sub
End Class
public partial class SalesOrderHeader
{
    // Update the order total.
    public void UpdateOrderTotal()
    {
        decimal newSubTotal = 0;

        // Ideally, this information is available in the EDM.
        decimal taxRatePercent = GetCurrentTaxRate();
        decimal freightPercent = GetCurrentFreight();

        // If the items for this order are loaded or if the order is 
        // newly added, then recalculate the subtotal as it may have changed.
        if (SalesOrderDetail.IsLoaded ||
            EntityState == EntityState.Added)
        {
            foreach (SalesOrderDetail item in this.SalesOrderDetail)
            {
                // Calculate line totals for loaded items.
                newSubTotal += (item.OrderQty *
                    (item.UnitPrice - item.UnitPriceDiscount));
            }

            this.SubTotal = newSubTotal;
        }

        // Calculate the new tax amount.
        this.TaxAmt = this.SubTotal
             + Decimal.Round((this.SubTotal * taxRatePercent / 100), 4);

        // Calculate the new freight amount.
        this.Freight = this.SubTotal
            + Decimal.Round((this.SubTotal * freightPercent / 100), 4);

        // Calculate the new total.
        this.TotalDue = this.SubTotal + this.TaxAmt + this.Freight;
    }
}

Cet exemple modifie une commande, puis appelle la méthode UpdateOrderTotal personnalisée sur SalesOrderHeader pour mettre à jour la propriété TotalDue. Comme l'attribut StoreGeneratedPattern="computed" du TotalDue est appliqué dans le fichier SSDL (Store Schema Definition Language), cette valeur mise à jour n'est pas enregistrée sur le serveur lorsque la méthode SaveChanges est appelée. Sans cet attribut, un objet UpdateException se produit si vous tentez de mettre à jour une colonne calculée sur le serveur.

Dim orderId As Integer = 43662

Using context As New AdventureWorksEntities
    Try
        ' Return an order and its items.
        Dim order As SalesOrderHeader = _
        context.SalesOrderHeader() _
        .Include("SalesOrderDetail") _
        .Where("it.SalesOrderID = @orderId", _
               New ObjectParameter("orderId", orderId)).First()

        Console.WriteLine("The original order total was: " _
            + order.TotalDue.ToString())

        ' Update the order status.
        order.Status = 1

        ' Increase the quantity of the first item, if one exists.
        If order.SalesOrderDetail.Count > 0 Then
            order.SalesOrderDetail.First().OrderQty += Convert.ToInt16(1)
        End If
        ' Increase the shipping amount by 10%.
        order.Freight = _
            Decimal.Round(order.Freight * Convert.ToDecimal(1.1), 4)

        ' Call the custom method to update the total.
        order.UpdateOrderTotal()

        Console.WriteLine("The calculated order total is: " _
            + order.TotalDue.ToString())

        ' Save changes in the object context to the database.
        Dim changes As Integer = context.SaveChanges()

        ' Refresh the order to get the computed total from the store.
        context.Refresh(RefreshMode.StoreWins, order)

        Console.WriteLine("The store generated order total is: " _
            + order.TotalDue.ToString())
    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    Catch ex As UpdateException
        Console.WriteLine(ex.ToString())
    End Try
End Using
int orderId = 43662;

using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    try
    {
        // Return an order and its items.
        SalesOrderHeader order =
            context.SalesOrderHeader
            .Include("SalesOrderDetail")
            .Where("it.SalesOrderID = @orderId", 
               new ObjectParameter("orderId", orderId)).First();

        Console.WriteLine("The original order total was: "
            + order.TotalDue);

        // Update the order status.
        order.Status = 1;

        // Increase the quantity of the first item, if one exists.
        if (order.SalesOrderDetail.Count > 0)
        {
            order.SalesOrderDetail.First().OrderQty += 1;
        }

        // Increase the shipping amount by 10%.
        order.Freight = 
            Decimal.Round(order.Freight * (decimal)1.1, 4);

        // Call the custom method to update the total.
        order.UpdateOrderTotal();
        
        Console.WriteLine("The calculated order total is: "
            + order.TotalDue);

        // Save changes in the object context to the database.
        int changes = context.SaveChanges();

        // Refresh the order to get the computed total from the store.
        context.Refresh(RefreshMode.StoreWins, order);

        Console.WriteLine("The store generated order total is: "
            + order.TotalDue);
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
    catch (UpdateException ex)
    {
        Console.WriteLine(ex.GetType().ToString() +": " + ex.ToString());
    }
}

Voir aussi

Concepts

Personnalisation des objets (Entity Framework)

Autres ressources

Utilisation d'objets personnalisés (Tâches Entity Framework)