如何:在对象上下文中管理数据并发性(实体框架)
本主题提供如何在对象上下文中管理并发性的示例。在本主题中,您将在更新 SalesOrderHeader 对象的 Status 属性时生成和处理 OptimisticConcurrencyException。有关更多信息,请参见保存更改和管理并发(实体框架)。
本主题中的示例基于 Adventure Works 销售模型。若要运行本示例中的代码,必须已将 AdventureWorks 销售模型添加到您的项目中,并将项目配置为使用 Entity Framework。为此,请完成如何:手动配置实体框架项目和如何:手动定义实体数据模型(实体框架) 中的过程。
为了成功地生成 OptimisticConcurrencyException,必须在概念映射文件中修改 Status 属性。
对 Status 属性启用并发检查
打开 AdventureWorks.csdl 文件并找到 SalesOrderHeader 实体的定义。
查找子 Status 元素,然后添加以下属性:
ConcurrencyMode="fixed"
保存对 AdventureWorks.csdl 的更改。
在以下示例代码中,在 foreach 循环(在 Visual Basic 中为 For Each)后设置断点,并在调试模式下运行应用程序。
当执行断开后,使用 SQL Server Management Studio 以针对 AdventureWorks 数据库执行以下 Transact-SQL 命令:
UPDATE Sales.SalesOrderHeader SET Status = 1 WHERE CreditCardApprovalCode IS NULL.
重新启动程序执行。
示例
在本示例中,当执行上述过程后,对 SalesOrderHeader 对象的 Status 属性所做的更改将导致出现 OptimisticConcurrencyException。
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.SalesOrderHeader.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 ex 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.SalesOrderHeader.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());
}
}