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 i file di modello e di mapping (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.SalesOrderDetails.IsLoaded OrElse EntityState = EntityState.Added Then
For Each item As SalesOrderDetail In Me.SalesOrderDetails
' 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 (this.SalesOrderDetails.IsLoaded ||
EntityState == EntityState.Added)
{
foreach (SalesOrderDetail item in this.SalesOrderDetails)
{
// 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()
' Return an order and its items.
Dim order As SalesOrderHeader = context.SalesOrderHeaders.Include("SalesOrderDetails") _
.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.SalesOrderDetails.Count > 0 Then
order.SalesOrderDetails.First().OrderQty += 1
End If
' Increase the shipping amount by 10%.
order.Freight = Decimal.Round(order.Freight * CDec(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.
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)
End Using
int orderId = 43662;
using (AdventureWorksEntities context =
new AdventureWorksEntities())
{
// Return an order and its items.
SalesOrderHeader order =
context.SalesOrderHeaders
.Include("SalesOrderDetails")
.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.SalesOrderDetails.Count > 0)
{
order.SalesOrderDetails.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);
}
Vedere anche
Concetti
Personalizzazione di oggetti (Entity Framework)
Definizione di una logica di business (Entity Framework)