Procedura: gestire la concorrenza dei dati nel contesto dell'oggetto (Entity Framework)
In questo argomento viene fornito un esempio di come gestire la concorrenza in un contesto dell'oggetto. In questo argomento viene generato e gestito un oggetto OptimisticConcurrencyException durante l'aggiornamento della proprietà Status dell'oggetto SalesOrderHeader. Per ulteriori informazioni, vedere Salvataggio delle modifiche e gestione della concorrenza (Entity Framework).
L'esempio incluso in questo argomento è basato 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).
Per generare correttamente un oggetto OptimisticConcurrencyException, è necessario modificare la proprietà Status nel file di mapping concettuale.
Per abilitare il controllo della concorrenza nella proprietà Status
Aprire il file AdventureWorks.csdl e individuare la definizione per l'entità SalesOrderHeader.
Individuare l'elemento Status figlio e aggiungere l'attributo seguente:
ConcurrencyMode="fixed"
Salvare le modifiche a AdventureWorks.csdl.
Nel codice di esempio seguente impostare un punto di interruzione dopo il cicloforeach (For Each in Visual Basic) ed eseguire l'applicazione in modalità di debug.
Quando l'esecuzione si interrompe, utilizzare SQL Server Management Studio per eseguire il comando Transact-SQL seguente nel database AdventureWorks:
UPDATE Sales.SalesOrderHeader SET Status = 1 WHERE CreditCardApprovalCode IS NULL.
Riavviare l'esecuzione del programma.
Esempio
In questo esempio le modifiche alla proprietà Status dell'oggetto SalesOrderHeader provocano la generazione di un oggetto OptimisticConcurrencyException quando viene eseguita la procedura precedente.
Using context As New AdventureWorksEntities()
Try
' Perform an operation with a high-level of concurrency.
' Change the status of all orders without an approval code.
Dim orders As ObjectQuery(Of SalesOrderHeader) = context.SalesOrderHeaders.Where("it.CreditCardApprovalCode IS NULL").Top("100")
For Each order As SalesOrderHeader In orders
' Reset the order status to 4 = Rejected.
order.Status = 4
Next
Try
' Try to save changes, which may cause a conflict.
Dim num As Integer = context.SaveChanges()
Console.WriteLine("No conflicts. " & num.ToString() & " updates saved.")
Catch generatedExceptionName As OptimisticConcurrencyException
' Resolve the concurrency conflict by refreshing the
' object context before re-saving changes.
context.Refresh(RefreshMode.ClientWins, orders)
' Save changes.
context.SaveChanges()
Console.WriteLine("OptimisticConcurrencyException handled and changes saved")
End Try
For Each order As SalesOrderHeader In orders
Console.WriteLine(("Order ID: " & order.SalesOrderID.ToString() & " Order status: ") + order.Status.ToString())
Next
Catch ex As UpdateException
Console.WriteLine(ex.ToString())
End Try
End Using
using (AdventureWorksEntities context =
new AdventureWorksEntities())
{
try
{
// Perform an operation with a high-level of concurrency.
// Change the status of all orders without an approval code.
ObjectQuery<SalesOrderHeader> orders =
context.SalesOrderHeaders.Where(
"it.CreditCardApprovalCode IS NULL").Top("100");
foreach (SalesOrderHeader order in orders)
{
// Reset the order status to 4 = Rejected.
order.Status = 4;
}
try
{
// Try to save changes, which may cause a conflict.
int num = context.SaveChanges();
Console.WriteLine("No conflicts. " +
num.ToString() + " updates saved.");
}
catch (OptimisticConcurrencyException)
{
// Resolve the concurrency conflict by refreshing the
// object context before re-saving changes.
context.Refresh(RefreshMode.ClientWins, orders);
// Save changes.
context.SaveChanges();
Console.WriteLine("OptimisticConcurrencyException "
+ "handled and changes saved");
}
foreach (SalesOrderHeader order in orders)
{
Console.WriteLine("Order ID: " + order.SalesOrderID.ToString()
+ " Order status: " + order.Status.ToString());
}
}
catch (UpdateException ex)
{
Console.WriteLine(ex.ToString());
}
}