Ho scritto un'applicazione .NET + EF. Tutto funziona bene su un singolo thread. Su più thread: è un'altra storia.Entity Framework aggiornamento e aggiornamento della concorrenza
Nel mio oggetto EF ho un contatore intero. Questa proprietà è contrassegnata come "Concurrency Mode = Fixed". Fondamentalmente, quello che sto cercando di fare è aggiornare questo contatore su diversi thread. Ti piace questa operazione:
this.MyCounter -= 1;
Perché è la modalità concorrenza è stata modificata in "Fixed", quando sto Tring per aggiornare una proprietà che è già cambia - un OptimisticConcurrencyException
viene generata.
Al fine di risolvere questi problemi di concorrenza, sto usando questo codice:
while (true)
{
try
{
this.UsageAmount -= 1; // Change the local EF object value and call SaveChanges().
break;
}
catch (OptimisticConcurrencyException)
{
Logger.Output(LoggerLevel.Trace, this, "concurrency conflict detected.");
EntityContainer.Instance.Entities.Refresh(RefreshMode.StoreWins, this.InnerObject);
}
}
Il risultato di questo codice è un ciclo infinito (o forse il suo aspetto proprio come). Ogni chiamata di this.UsageAmount -= 1
genera un OptimisticConcurrencyException
, che fa ricominciare il ciclo.
My EntityContainer.Instance.Entities
è una classe singleton che fornisce un contesto EF PER FILO. Ciò significa che ogni thread ha un contesto unico. Il codice:
public sealed class EntityContainer
{
#region Singlethon Implemantation
private static Dictionary<Thread, EntityContainer> _instance = new Dictionary<Thread,EntityContainer>();
private static object syncRoot = new Object();
public static EntityContainer Instance
{
get
{
if (!_instance.ContainsKey(Thread.CurrentThread))
{
lock (syncRoot)
{
if (!_instance.ContainsKey(Thread.CurrentThread))
_instance.Add(Thread.CurrentThread, new EntityContainer());
}
}
return _instance[Thread.CurrentThread];
}
}
private EntityContainer()
{
Entities = new anticopyEntities2();
}
#endregion
anticopyEntities2 _entities;
public anticopyEntities2 Entities
{
get
{
//return new anticopyEntities2();
return _entities;
}
private set
{
_entities = value;
}
}
}
BTW, dopo aver chiamato i metodi Entities.Refresh
- sembra che tutto funzioni (stato oggetto è invariato e il valore propery è esattamente ciò che esiste nel database).
Come posso risolvere questo problema di concorrenza?
Potresti inserire il codice per la classe Singleton lei ha citato 'EntityContainer.Instance.Entities'? - Solo la parte in cui stai fornendo "un contesto EF per thread". – lukiffer
Il codice EntityContainer.Instance.Entities viene inserito nel post. – No1Lives4Ever
Quando si pronuncia * ogni * richiamo di chiamata, questo potrebbe essere impedito ad alcuni thread di fare aggiornamenti perché vengono battuti sul database ogni volta? Il valore nel DB sta effettivamente cambiando? – shambulator