Sto lavorando su un'applicazione .NET dove carico il mio DB di lavoro (operazioni di salvataggio) su un thread separato (ispirato da come NodeJS gestisce le operazioni IO). Un'operazione di salvataggio si riduce a questa (utilizzando Entity Framework):
public void Save(Customer customer)
{
Task.Factory.StartNew(() =>
{
using (var entities = new MyEntities())
{
var persistedCustomer
= entities.Customers.FirstOrDefault(x => x.Number == customer.Number);
if (persistedCustomer == null)
{
persistedCustomer = new DBCustomer();
// set properties
entities.Customers.AddObject(persistedCustomer);
}
else
{
// set properties
}
entities.SaveChanges();
}
});
}
Quindi, in sostanza:
- controlla se l'entità esiste già nel DB
- in caso contrario, creane uno nuovo
- se già esiste, aggiorna quello esistente
Dove questo a volte si rompe è quando due chiamate al metodo Save vengono eseguite contemporaneamente. Entrambi i thread vedono che l'entità non esiste ancora e vogliono fare un inserto. Una condizione di gara standard.
Come faresti a risolvere questo problema? Qualche esperienza con questo?
Potrei implementare un meccanismo di tentativi, ma mi chiedevo se ci sono altre opzioni. Ovviamente, un semplice tentativo potrebbe sovrascrivere alcune proprietà che il salvataggio precedente aveva aggiornato.