Sto pre-caricando i dati dei prodotti sul mio sito web perché ho bisogno che questo sia accessibile velocemente e preferirei che questo venga caricato una volta all'avvio dell'applicazione anziché solo quando è richiesta. Questo è un modo per assicurarsi che le cose si caricino velocemente. Lo faccio caricando avidamente la mia entità di prodotto insieme ad altre entità e memorizzandole nella memoria.
Quindi ho qualcosa di simile al seguente per recuperare i miei dati:
public override IEnumerable<Product> Get()
{
var result = _cacheManager.Get(PreLoadCacheKey) as IEnumerable<Product>;
if (result != null)
return result;
return base.Get();
}
Il problema che sto affrontando è che con me, usando l'iniezione delle dipendenze, non controllo l'ambito del mio contesto dati (oltre a impostarlo su InstancePerRequest () e lasciandolo), quindi quando memorizzo le mie entità in cache hanno ancora un riferimento a il contesto originale.
Ho provato varie cose ma non riesco a risolvere il problema di:
The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.
quando si tenta di collegare un'entità recuperata dalla cache a una nuova entità che sto aggiungendo al database.
Cose che ho provato:
AsNoTracking()
Detach
dal contesto corrente, quindi collegarli al nuovo contesto sul recupero dalla cache. Idealmente, mi piacerebbe essere in grado di staccare un contesto da un'entità dal lato dell'entità in modo da poter vedere se l'entità è collegata al contesto corrente e, in caso contrario, staccarla da quella vecchia e collegarla al nuovo. Da quello che ho visto, però, l'unico che puoi staccare è avere un riferimento al vecchio contesto che non avrò.
Mi manca qualcosa di ovvio?
modificare
Questo è un esempio in cui collegheremo l'entità a un altro contesto:
var orderLine = order.Lines.FirstOrDefault(ol => ol.Product.Id == product.Id) ?? new SalesOrderLine();
orderLine.Price = price.Price;
orderLine.Product = product; //This is my cache'd entity.
orderLine.ProductPriceType = price.ProductPriceType;
orderLine.Quantity += qty;
order.Customer = customer;
order.Lines.Add(orderLine);
order.Status = SalesOrderStatus.Current;
Update(order);
SaveChanges();
Allo stato attuale, sto caricando forzatamente una versione senza cache per ovviare a questo problema.
Il recupero dei dati memorizzati nella cache con AsNoTracking
è il primo passo. Ma (apparentemente) gli oggetti nella cache sono creati come proxy, quindi sono consapevoli di essere stati creati da un altro contesto.
Quindi assicurati che nessun proxy, ma solo i POCO siano memorizzati nella cache, cosa che devi fare disabilitando la creazione del proxy nel contesto che recupera gli oggetti nella cache:
db.Configuration.ProxyCreationEnabled = false;
(dove db
è l'istanza di DbContext
).
Quindi assicurati di collegare l'oggetto a un nuovo contesto prima di usarlo lì. Questo è importante, perché se si Add()
una nuova OrderLine
, EF potrebbe provare ad aggiungere un nuovo Product
.
Vorrei aggiungere che tutto questo sarebbe molto più semplice se avessi esposto OrderLine.ProductId
nel tuo modello di entità: basta impostare il valore di identificazione sarebbe sufficiente.