sql >> Databáze >  >> RDS >> Sqlserver

.NET Entity Framework a transakce

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.



  1. Možnosti multitenance pro PostgreSQL

  2. Vytahování obrazových dat BLOB z MySQL v PHP

  3. Nelze se připojit k databázi Postgres pomocí zásobníku Bitnami Django

  4. Najít rodiče rekurzivně pomocí Query