Condividi tramite


Procedura: personalizzare oggetti dati generati (Entity Framework)

In questo argomento viene illustrato come aggiungere un metodo personalizzato a una classe di dati generata. Gli esempi inclusi in questo argomento sono basati sul modello Sales di AdventureWorks. Per eseguire il codice incluso in questo esempio, è necessario avere già aggiunto il modello Sales di AdventureWorks al progetto e avere configurato il progetto per l'utilizzo di Entity Framework. A tale scopo, completare le procedure descritte in Procedura: configurare manualmente un progetto di Entity Framework e Procedura: definire manualmente un modello EDM (Entity Framework).

Esempio

In questo esempio viene definito un metodo UpdateOrderTotal personalizzato per la classe SalesOrderHeader generata. Questo metodo personalizzato consente di aggiornare la proprietà TotalDue in base ai valori correnti di imposta, trasporto e totali dei singoli articoli. Questo metodo è definito come classe parziale in modo che non venga perso quando la classe SalesOrderHeader viene rigenerata dagli strumenti di 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;
    }
}

In questo esempio un ordine viene modificato, quindi viene chiamato il metodo UpdateOrderTotal personalizzato su SalesOrderHeader per aggiornare la proprietà TotalDue. Poiché a TotalDue è applicato l'attributo StoreGeneratedPattern="computed" nel file SSDL (Store Schema Definition Language), questo valore aggiornato non viene salvato nel server quando viene chiamato SaveChanges. Senza questo attributo, se si tenta di aggiornare una colonna calcolata nel server si verifica un evento UpdateException.

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

Vedere anche

Concetti

Personalizzazione di oggetti (Entity Framework)

Altre risorse

Utilizzo di oggetti personalizzati (attività di Entity Framework)