sql >> Database teknologi >  >> RDS >> Sqlserver

.NET Entity Framework og transaktioner

Oprettelse af én global enhedsramme DbContext i en webapplikation er meget dårlig. DbContext klasse er ikke trådsikker (og det samme gælder for Entity Framework v1's ObjectContext klasse). Det er bygget op omkring konceptet arbejdsenheden og det betyder, at du bruger det til at drive en enkelt brugssag:altså til en forretningstransaktion. Det er beregnet til at håndtere en enkelt anmodning.

Undtagelsen, du får, sker, fordi du for hver anmodning opretter en ny transaktion, men prøv at bruge den samme DbContext . Du er heldig, at DbContext opdager dette og kaster en undtagelse, for nu har du fundet ud af, at dette ikke vil virke.

DbContext indeholder en lokal cache af enheder i din database. Det giver dig mulighed for at foretage en masse ændringer og til sidst indsende disse ændringer til databasen. Når du bruger en enkelt statisk DbContext , med flere brugere, der kalder SaveChanges på det objekt, hvordan skal det vide, hvad der præcist skal begås, og hvad der ikke bør?

Fordi den ikke ved det, gemmer den alt ændringer, men på det tidspunkt kan en anden anmodning stadig foretage ændringer. Når du er heldig, vil enten EF eller din database fejle, fordi entiteterne er i en ugyldig tilstand. Hvis du er uheldig, bliver enheder, der er i en ugyldig tilstand, gemt i databasen, og du finder muligvis ud af uger senere, at dine data er blevet beskadiget.

Løsningen på dit problem er at oprette mindst én DbContext pr. anmodning . Selvom du i teorien kunne cache en objektkontekst i brugersessionen, er dette også en dårlig idé, for i så fald er DbContext vil typisk leve for længe og vil indeholde forældede data (fordi dens interne cache ikke automatisk bliver opdateret).

Bemærk også, at have én DbContext per tråd er omtrent lige så slemt som at have én enkelt instans til den komplette webapplikation. ASP.NET bruger en trådpulje, hvilket betyder, at en begrænset mængde tråde vil blive oprettet i løbet af en webapplikations levetid. Dette betyder grundlæggende, at disse DbContext instanser vil i så fald stadig leve i hele applikationens levetid, hvilket forårsager de samme problemer med forældede data.

Du tror måske, at have én DbContext pr. tråd er faktisk trådsikker, men dette er normalt ikke tilfældet, da ASP.NET har en asynkron model, der tillader efterbehandlingsanmodninger på en anden tråd, end hvor den blev startet (og de nyeste versioner af MVC og Web API tillader endda en vilkårligt antal tråde håndterer en enkelt anmodning i sekventiel rækkefølge). Det betyder, at den tråd, der startede en anmodning og skabte ObjectContext kan blive tilgængelig til at behandle en anden anmodning længe før den oprindelige anmodning blev afsluttet. De objekter, der blev brugt i denne anmodning (såsom en webside, controller eller enhver virksomhedsklasse), kan dog stadig referere til den DbContext . Da den nye webanmodning kører i den samme tråd, vil den få den samme DbContext instans som det, den gamle anmodning bruger. Dette forårsager igen løbsforhold i din applikation og forårsager de samme trådsikkerhedsproblemer som en global DbContext instans forårsager.



  1. mysql_fetch_array() returnerer 'det leverede argument er ikke en gyldig MySQL-resultatressource'

  2. Knee-Jerk PerfMon tællere:Sidelevetid

  3. Hvordan kontrollerer man, hvornår autovækst sidst er udført?

  4. Hvor findes MySQL-databasefilerne for WAMP?