Vytvoření jednoho globálního Entity Framework DbContext
ve webové aplikaci je velmi špatné. DbContext
třída není bezpečná pro vlákna (a totéž platí pro ObjectContext
Entity Framework v1 třída). Je postaven na konceptu jednotky práce
a to znamená, že jej používáte k provozování jednoho případu použití:tedy pro obchodní transakci. Je určen ke zpracování jednoho jediného požadavku.
Výjimka, kterou získáte, se stane, protože pro každý požadavek vytvoříte novou transakci, ale zkuste použít stejný DbContext
. Máte štěstí, že DbContext
detekuje to a vyvolá výjimku, protože teď jste zjistili, že to nebude fungovat.
DbContext
obsahuje lokální mezipaměť entit ve vaší databázi. Umožňuje vám provést spoustu změn a nakonec tyto změny odeslat do databáze. Při použití jednoho statického DbContext
, přičemž více uživatelů volá SaveChanges
na tomto objektu, jak má vědět, co přesně by se mělo dopustit a co ne?
Protože to neví, uloží vše změny, ale v tom okamžiku může stále ještě provádět změny jiný požadavek. Když budete mít štěstí, EF nebo vaše databáze selže, protože entity jsou v neplatném stavu. Pokud budete mít smůlu, entity, které jsou v neplatném stavu, se úspěšně uloží do databáze a o týdny později můžete zjistit, že vaše data byla poškozena.
Řešením vašeho problému je vytvořit alespoň jeden DbContext
na žádost
. I když teoreticky můžete kontext objektu v uživatelské relaci uložit do mezipaměti, je to také špatný nápad, protože v takovém případě DbContext
bude obvykle žít příliš dlouho a bude obsahovat zastaralá data (protože jeho interní mezipaměť nebude automaticky obnovena).
Všimněte si také, že máte jeden DbContext
na vlákno je asi tak špatné jako mít jednu jedinou instanci pro celou webovou aplikaci. ASP.NET používá fond vláken, což znamená, že během životnosti webové aplikace bude vytvořeno omezené množství vláken. To v podstatě znamená, že tyto DbContext
instance budou v takovém případě stále žít po celou dobu životnosti aplikace, což způsobí stejné problémy se zastaralostí dat.
Možná si myslíte, že mít jeden DbContext
na vlákno je ve skutečnosti bezpečné pro vlákna, ale obvykle tomu tak není, protože ASP.NET má asynchronní model, který umožňuje dokončení požadavků na jiném vláknu, než kde bylo spuštěno (a nejnovější verze MVC a webového rozhraní API dokonce umožňují libovolný počet vláken zpracovává jeden požadavek v sekvenčním pořadí). To znamená, že vlákno, které spustilo požadavek a vytvořilo ObjectContext
mohou být k dispozici pro zpracování jiného požadavku dlouho před dokončením původního požadavku. Objekty použité v tomto požadavku (jako je webová stránka, řadič nebo jakákoli obchodní třída) však mohou stále odkazovat na DbContext
. Protože nový webový požadavek běží ve stejném vlákně, získá stejný DbContext
instance jako to, co používá starý požadavek. To opět způsobuje konflikty ve vaší aplikaci a způsobuje stejné problémy s bezpečností vláken jako globální DbContext
instance příčiny.