Niedawno wprowadziłem zmiany w mojej aplikacji MVC3, próbując prawidłowo pozbyć się obiektów DbContext
[1]. To zadziałało świetnie, ale kiedy aplikacja została zepchnięta na mój serwer produkcyjny, zacząłem sporadycznie uzyskiwać zabawne wyjątki, które utrzymały się do czasu, aż AppPool zostanie poddany recyklingowi. Wyjątkiem może być wstecz do kodu w moim zwyczaju AuthorizeAttribute
i wyglądać tak:Problemy po usunięciu DbContext
System.InvalidOperationException: The 'Username' property on 'User' could not be set to a 'Int32' value. You must set this property to a non-null value of type 'String'.
System.InvalidOperationException: The 'Code' property on 'Right' could not be set to a 'String' value. You must set this property to a non-null value of type 'Int32'.
(schematu bazy danych wygląda następująco: Użytkownicy: [Guid, String ...] Prawa: [Guid, Int32,. ..])
To tak, jakby niektóre "przewody zostały skrzyżowane", a aplikacja miesza wyniki z bazy danych: próbując zmaterializować wynik Right
jako User
i vice versa.
Aby zarządzać wyrzucaniem DbContext
, wstawiam kod, aby zapisać go na poziomie kontrolera. Po usunięciu kontrolera, dysponuję również DbContext
. Wiem, że to jest hacky, ale AuthorizeAttribute
używa tego samego kontekstu przez filterContext.Controller
.
Czy jest coś nie tak z obchodzeniem się z cyklem życia obiektu DbContext
w tej posiadłości? Czy są jakieś logiczne wyjaśnienia, dlaczego otrzymuję powyższe wyjątki krzyżowe?
[1] Chociaż rozumiem, że nie jest konieczne dysponowanie obiektami DbContext
, niedawno natknąłem się na wiele źródeł stwierdzających, że była to najlepsza praktyka niezależnie.
Edit (za @ komentarzu MikeSW za)
Właściwość z AuthorizeAttribute
reprezentujących DbContext
jest ustawiany w metodzie OnAuthorization
, gdy AuthorizationContext
jest w zasięgu. Ta właściwość jest później używana w metodzie AuthorizeCore
.
Czy możesz udostępnić niektóre z odpowiednich kodów niestandardowego AuthorizeAttribute? Zauważ, że atrybut jest używany jako singleton przez asp.net mvc. Czy używasz również pojemnika DI? – MikeSW
@MikeSW Dodałem informację o powyższym użytkowaniu. Nie używam pojemnika DI. Dzięki informacjom podanym powyżej wydaje się, że te błędy występują ze względu na współbieżność: w czasie między 'OnAuthorization' i' AuthorizeCore', inne żądanie wyzwala 'OnAuthorization' i blokuje właściwość' DbContext'. Czy to następuje? –
Tak, to twój problem. [Upoważnij] to w zasadzie singleton i zmieniasz właściwość dbcontext przy każdym żądaniu. Proponuję użyć DI Container, zarejestrować DbContext z HttpPerInstance lifetime następnie użyć DependencyResolver.Current.GetService() w metodzie OnAuthorization. Kontener powinien obsługiwać także DbContext –
MikeSW