public class ProductService
{
private readonly IDbContextFactory _factory;
public ProductService(IDbContextFactory factory)
=> _factory = factory;
public async Task GetByIdAsync(int id)
{
await using var context = await _factory.CreateDbContextAsync();
return await context.Products.FindAsync(id);
}
public async Task UpdateStockQuantityAsync(int id, int updateQuantity)
{
await using var context = await _factory.CreateDbContextAsync();
var product = await context.Products.FindAsync(id);
if (product is null) return;
product.Quantity += updateQuantity;
await context.SaveChangesAsync();
}
}
Observe que ProductService tem dois métodos, GetByIdAsync e UpdateStockQuantityAsync. Uma instância do DbContext classe é criada localmente em cada um desses métodos. Agora, suponha que você tenha duas threads, T1 e T2, que executam esses métodos simultaneamente. Ou seja, a thread T1 executa o GetByIdAsync método enquanto o thread T2 executa o UpdateStockQuantityAsync método. Como cada um desses métodos é executado isoladamente, eles terão seu próprio contexto, conexão e informações de controle de alterações, e não haverá estado mutável, portanto, você não precisará implementar a sincronização de threads em nenhum desses métodos.
Considere o código a seguir que executa uma operação de leitura e uma operação de atualização em duas tarefas separadas.
public static async Task RunMethodsInParallelAsync(ProductService productService)
{
Task readTask = productService.GetByIdAsync(1);
Task updateTask = productService.UpdateStockQuantityAsync(3, 5);
await Task.WhenAll(readTask, updateTask);
Product? product = await readTask;
}
O Task.WhenAll O método executa as duas tarefas em paralelo e espera até que ambas terminem. A razão pela qual essa abordagem é segura para threads e não cria erros de simultaneidade é que cada um desses dois métodos cria seu próprio DbContext instância internamente. Portanto, a operação de leitura e a operação de atualização usam DbContext instâncias.
