User A reads product (Version = 1)
User B reads product (Version = 1)
User A updates price to 50, saves (Version = 1 → 2)
User B updates price to 60, saves (Version = 1 → ?)
↓
CONFLICT - User B should fail!
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
// Sử dụng property khác làm concurrency token
public DateTime UpdatedAt { get; set; }
}
// Cấu hình
modelBuilder.Entity<Product>()
.Property(p => p.UpdatedAt)
.IsConcurrencyToken();
// Pessimistic lock example
await using var transaction = await context.Database.BeginTransactionAsync();
var product = await context.Products
.FromSqlRaw("SELECT * FROM Products WITH (UPDLOCK) WHERE Id = {0}", id)
.FirstAsync();
// Update product
product.Price = newPrice;
await context.SaveChangesAsync();
await transaction.CommitAsync();