Skip to content

Instantly share code, notes, and snippets.

@danielplawgo
Created November 6, 2020 08:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielplawgo/9bfbea4c1038b88659e7ca4d34e8c605 to your computer and use it in GitHub Desktop.
Save danielplawgo/9bfbea4c1038b88659e7ca4d34e8c605 to your computer and use it in GitHub Desktop.
Optymistyczna współbieżność w EF Core
public class DataContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=.\SQLEXPRESS;Database=EFCoreOptimisticConcurrency;Trusted_Connection=True;");
}
public DbSet<Product> Products { get; set; }
}
public class DataContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=.\SQLEXPRESS;Database=EFCoreOptimisticConcurrency;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
public DbSet<Product> Products { get; set; }
}
private static async Task EditProduct(Guid productId, Action<Product> editAction, int delay)
{
await using var db = new DataContext();
var product = await db.Products.FirstOrDefaultAsync(p => p.Id == productId);
await Task.Delay(delay);
editAction(product);
await db.SaveChangesAsync();
}
private static async Task EditProduct(Guid productId, Action<Product> editAction, int delay)
{
await using var db = new DataContext();
try
{
var product = await db.Products.FirstOrDefaultAsync(p => p.Id == productId);
await Task.Delay(delay);
editAction(product);
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
var databaseValues = await entry.GetDatabaseValuesAsync();
foreach (var property in entry.CurrentValues.Properties)
{
var proposedValue = entry.CurrentValues[property];
var databaseValue = databaseValues[property];
var originalValue = entry.OriginalValues[property];
if (proposedValue.Equals(databaseValue) || originalValue.Equals(databaseValue) || property.Name == "RowVersion")
{
continue;
}
Console.WriteLine($"ProposedValue: {proposedValue}, DatabaseValue: {databaseValue}, OriginalValue: {originalValue}.");
//proposedValues[property] = wartość do zapisu;
}
entry.OriginalValues.SetValues(databaseValues);
}
}
}
static async Task Main(string[] args)
{
var productId = Guid.Parse("E440B325-AD1F-4B4D-9162-36DFB0F3A357");
await Setup(productId);
var tasks = new[]
{
EditProduct(productId, p => p.Price = 11, 1000),
EditProduct(productId, p => p.Price = 12, 100)
};
await Task.WhenAll(tasks);
var product = await GetProduct(productId);
Console.WriteLine($"Product: {product.Name}, price: {product.Price}");
}
EditProduct(productId, p => p.Price = 11, 1000),
EditProduct(productId, p => p.Name = "new product", 100)
public class Product
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Name { get; set; }
public decimal Price { get; set; }
}
public class Product
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Name { get; set; }
public decimal Price { get; set; }
public byte[] RowVersion { get; set; }
}
public class ProductEntityTypeConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.Property(p => p.RowVersion)
.IsRowVersion();
}
}
private static async Task Setup(Guid productId)
{
await using var db = new DataContext();
var product = await db.Products.FirstOrDefaultAsync(p => p.Id == productId);
if (product == null)
{
product = new Product()
{
Id = productId
};
await db.Products.AddAsync(product);
}
product.Name = "product";
product.Price = 10;
await db.SaveChangesAsync();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment