CRUD-operasjoner med koblede data.

Siste oppdatering: 08.04.2017

De fleste dataoperasjoner er på en eller annen måte CRUD-operasjoner (Create, Read, Update, Delete), det vil si opprettelse, mottak, oppdatering og sletting. Entity Framework Core gjør det enkelt å gjøre alle disse tingene.

La oss for eksempel lage et prosjekt av typen Console App (.NET Core). Og etter å ha opprettet prosjektet, vil vi umiddelbart legge til EF Core-funksjonalitet til det. For å gjøre dette, legg til prosjektet via NuGet-pakker Microsoft.EntityFrameworkCore.SqlServer Og Microsoft.EntityFrameworkCore.Tools.

Deretter vil vi legge til en brukerklasse til prosjektet, hvis objekter vil bli lagret i databasen:

Offentlig klasse Bruker ( offentlig int Id ( get; sett; ) offentlig streng Navn ( get; sett; ) offentlig int Alder ( get; sett; ) )

Og legg til ApplicationContext-datakontekstklassen:

Bruker Microsoft.EntityFrameworkCore; navneområde HelloApp ( offentlig klasse ApplicationContext: DbContext ( offentlig DbSet Brukere ( get; set; ) public ApplicationContext() ( Database.EnsureCreated(); ) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) ( optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=helloappeTrustedConnection; "); ) ) )

Bruke System; bruker System.Linq; navneområde HelloApp ( public class Program ( public static void Main(string args) ( // Legger til ved hjelp av (ApplicationContext db = new ApplicationContext()) ( Bruker bruker 1 = ny bruker ( Navn = "Tom", Alder = 33 ); Bruker bruker2 = ny bruker ( Navn = "Alice", Alder = 26 ); // Legger til db.Users.Add(bruker1); db.Users.Add(bruker2); db.SaveChanges(); ) // få bruk (ApplicationContext db = new ApplicationContext()) ( // hente objekter fra databasen og sende ut til konsollen var users = db.Users.ToList(); Console.WriteLine("Data etter å ha lagt til:"); foreach ( User u in users) ( Console.WriteLine($"(u.Id).(u.Name) - (u.Age)"); ) ) // Redigering med (ApplicationContext db = new ApplicationContext()) ( // få det første User object user = db.Users.FirstOrDefault(); if(user!=null) ( user.Name = "Bob"; user.Age = 44; //oppdater objektet //db.Users. Update(user) ; db.SaveChanges(); ) // vis data etter oppdatering av Console.WriteLine("\nData etter redigering:"); var users = db.Users.ToList(); foreach (User u in users) ( Console.WriteLine( $"(u.Id).(u.Name) - (u.Age)"); ) ) // Sletter ved å bruke (ApplicationContext db = new ApplicationContext()) ( // få den første brukerobjektbrukeren = db.Users. FirstOrDefault(); if (bruker != null) ( //sletter objektet db.Users.Remove(user); db.SaveChanges(); ) // sender ut data etter oppdatering av Console.WriteLine("\ nData etter sletting:" ; var users = db.Users.ToList(); foreach (Bruker u i brukere) ( Console.WriteLine($"(u.Id).(u.Name) - (u.Age)"); ) ) Console.Read(); ) ) )

Og etter utførelse vil vi få følgende konsollutgang:

Data etter å ha lagt til 1.Tom - 33 2.Alice - 26 Data etter redigering 1.Bob - 44 2.Alice - 26 Data etter sletting 2.Alice - 26

Addisjon

For å legge til et objekt, bruk Add-metoden, definert i DbSet-klassen, som det tilføyde objektet sendes til:

Db.Users.Add(bruker2); db.SaveChanges();

Add-metoden setter Added som tilstanden til det nye objektet. Derfor vil db.SaveChanges()-metoden generere en INSERT-setning for å sette inn modellen i tabellen.

Hvis vi trenger å legge til flere objekter samtidig, kan vi bruke AddRange()-metoden:

Bruker bruker1 = ny bruker ( Navn = "Tom", Alder = 33 ); Bruker bruker2 = ny bruker ( Navn = "Alice", Alder = 26 ); db.Users.AddRange(bruker1, bruker2);

Fjerning

Fjerning gjøres ved å bruke Fjern-metoden:

Db.Users.Remove(bruker); db.SaveChanges();

Denne metoden vil sette objektets status til Deleted, noe som får Entity Framework til å generere en DELETE SQL-setning når db.SaveChanges()-metoden kjøres.

Hvis du trenger å fjerne flere objekter samtidig, kan du bruke RemoveRange()-metoden:

Bruker bruker1 = db.Users.FirstOrDefault(); Bruker bruker2 = db.Users.LastOrDefault(); db.Users.RemoveRange(bruker1, bruker2);

Redigering

Når et objekt endres, sporer selve Entity Framework alle endringer, og når SaveChanges()-metoden kalles, vil en UPDATE SQL-setning bli generert for dette objektet, som vil oppdatere objektet i databasen.

Men det skal bemerkes at i i dette tilfellet Effekten av datakonteksten er begrenset til grensene for brukskonstruksjonen. Men la oss se på et annet eksempel. Vi mottar et objekt ett sted og oppdaterer det et annet. For eksempel:

Bruker bruker = null; ved å bruke (ApplicationContext db = new ApplicationContext()) ( // få objektet bruker = db.Users.FirstOrDefault(); Console.WriteLine("Data før redigering:"); var users = db.Users.ToList(); foreach ( Bruker u i brukere) ( Console.WriteLine($"(u.Id).(u.Name) - (u.Alder)"); ) ) //............. ..... // Redigering med (ApplicationContext db = new ApplicationContext()) ( // Editing if (user != null) ( user.Name = "Sam"; user.Age = 33; ) db.SaveChanges( ); // vis data etter oppdatering Console.WriteLine("\nData etter redigering:"); var users = db.Users.ToList(); foreach (var u i brukere) ( Console.WriteLine($"(u.Id) ) .(u.Name) - (u.Age)"); ) )

Til tross for at brukerobjektet ikke er null og finnes i databasen, vil det tilsvarende objektet i databasen ikke oppdateres i den andre bruksblokken. Og i dette tilfellet må vi bruke oppdateringsmetoden:

// Redigering med (ApplicationContext db = new ApplicationContext()) ( // Editing if (user != null) ( user.Name = "Sam"; user.Age = 33; db.Users.Update(user); ) db .SaveChanges(); // vis data etter oppdatering Console.WriteLine("\nData etter redigering:"); var users = db.Users.ToList(); foreach (var u i brukere) ( Console.WriteLine($"( u.Id).(u.Name) - (u.Age)"); ) )

Hvis det er nødvendig å oppdatere flere objekter samtidig, brukes UpdateRange()-metoden:

Db.Users.UpdateRange(bruker1, bruker2);

Jeg er en ny SQL Server DBA, jeg hørte om CRUD-akronymet, men jeg forstår ikke helt betydningen og viktigheten av disse CRUD-operasjonene, kan du gi en detaljert forklaring?

Løsning

CRUD er de grunnleggende operasjonene i enhver RDBMS, og dette tipset vil ta en detaljert titt på CRUD-operasjonene i SQL Server.

Hva er CRUD?

CRUD betyr Opprett, Les, Oppdater, Slett, og det kan bety forskjellige ting i forskjellige systemer, men for SQL Server anses det vanligvis å kartlegge til følgende SQL-operasjoner på tabellposter.

CRUD SQL
C - Opprett Sett inn
R - Les Plukke ut
U-oppdatering Oppdater
D - Slett Slett

Her er to eksempler

I SQL Server 2008 er det en MERGE-setning som kan oppnå funksjonene til CUD (ingen R). Jeg utelater det med vilje her siden det ikke er tilgjengelig på alle SQL Server-versjoner, og det er også umulig å klassifisere det til C eller U eller D.

Utvider CRUD-konseptet

CRUD ser i hovedsak ut til å være DML (datamanipulasjonsspråk), men dette konseptet kan utvides til DDL (Data Definition Language). For eksempel, hvis vi anser en database som en beholder, kan vi CRUD mange databaseobjekter, som tabell, visning, lagret prosedyre og bruker, etc. La oss bruke en tabell som et objekt, vi kan se følgende CRUD-handlinger.

Yii er et rammeverk med høy ytelse som er raskt, sikkert og godt egnet for Webapplikasjoner 2.0.

Den støtter konvensjoner over konfigurasjon, noe som betyr at hvis du følger rammeverkets retningslinjer, vil du ende opp med å skrive mye mindre kode enn hvis du ikke fulgte dem (og mindre kode inneholder færre feil).

I tillegg tilbyr rammeverket mange praktiske, ferdige funksjoner, som: stillas, datatilgangsobjekter, tema, tilgangskontroll, caching og mye mer. I denne artikkelen vil jeg dekke det grunnleggende om hvordan du lager et CRUD-system ved hjelp av Yii.

La oss komme i gang

Jeg antar at du allerede har installert og lastet ned den siste stabile versjonen (i skrivende stund - versjon 1.1.13).

Pakk ut zip-filen for å få tak i yii-1.1.13.e9e4a0-mappen (versjons-IDen kan variere avhengig av versjonen du lastet ned), endre navn på mappen til yii, og plasser den i den netttilgjengelige rotkatalogen din.

I mitt tilfelle er dette C:wampwww, så banen til rammefilene vil være: C:wampwwwyii .

Jeg vil referere til det som gjennom hele artikkelen, slik at du enkelt kan følge alle trinnene, selv om innstillingene dine er forskjellige fra mine.

Deretter må vi sjekke hvilke Yii-funksjoner som vil bli støttet av systemet vårt. Åpne lenken http://localhost/yii/requirements i nettleseren din for å se detaljer om rammekravene.

Siden vi skal jobbe med en MySQL-database, MYSQL-utvidelse PUD må være aktivert.

Vi ønsket å raskt sjekke Yii-kravene, så vi plasserte filene i en tilgjengelig katalog, men det anbefales å lagre Yii-filer utenfor en nettverkskatalog. Når du er verifisert, kan du flytte Yii-filene hvor som helst du vil.

La oss gå videre

Hver nettapplikasjon har sin egen katalogstruktur, og Yii-applikasjoner må også opprettholde en hierarkisk struktur i nettkatalogen.

For å lage en skjelettapplikasjon med en passende katalogstruktur kan du bruke Yii-verktøyet yiic, som kjører fra kommandolinjen. Gå til nettverkskatalogen og skriv inn følgende:

frameworkyiic webapp yiitest

Denne kommandoen vil lage en skjelettapplikasjon kalt yiitest with minimumssett nødvendige filer. Inne finner du en index.php-fil som fungerer som et påloggingsskript, den aksepterer brukerforespørsler og bestemmer hvilken kontroller som skal håndtere forespørselen.

Yii-rammeverket er basert på MVC- og OOP-prinsipper, så du må forstå disse emnene. Hvis du er ny på MVC, sjekk ut The MVC Pattern and PHP-serien, som gir en god introduksjon til emnet.

I Yii ser URL-en slik ut http://localhost/yiitest/index.php?r=controllerID/actionID. For eksempel, i et bloggingsystem kan nettadressen være: http://localhost/yiitest/index.php?r=post/create. post er kontroller-ID, og ​​opprette er handlings-ID.

Basert på ID-ene bestemmer innloggingsskriptet hvilken kontroller og metode som skal ringes.

En kontroller som har identifikasjonsposten må hete PostController (identifikatoren oppnås ved å fjerne kontrollørens suffiks fra klassenavnet og endre den første bokstaven til liten bokstav).

Handlings-ID– dette er identifikatoren for metoden representert i kontrolleren på lignende måte; Inne i PostController skal det være en metode kalt actionCreate() .

Det kan være flere visninger knyttet til en enkelt kontroller, så vi lagrer visningsfiler i beskyttede/views/controllerID-mapper.

Vi kan lage en visningsfil for kontrolleren vår kalt create.php i katalogen beskrevet ovenfor, og deretter presentere den for brukere ved ganske enkelt å skrive følgende kode i actionCreate():

offentlig funksjon actionCreate() ( $this->render("skape"); )

Om nødvendig kan du også sende tilleggsdata til visningen. Dette gjøres som følger:

$this->render("opprett", array("data" => $data_item));

Inne i visningsfilen kan vi få tilgang til dataene gjennom $data-variabelen.

Visningen har også tilgang til $this-variabelen, som peker på kontrollerforekomsten som gjengir visningen.

I tillegg, hvis du vil ha brukervennlige URL-er, kan du fjerne kommentarene til følgende kodebit i din protected/config/main.php-fil:

"urlManager"=>array("urlFormat"=>"bane", "rules"=>array(" /"=>"/visning", " //"=>"/", "/"=>"/",)

Da vil nettadressene se slik ut: http://localhost/yiitest/controllerID/actionID.

CRUD applikasjonsutvikling

Nå som du kjenner de viktige Yii-konvensjonene, er det på tide å komme i gang med CRUD. I denne delen skal vi utvikle et enkelt system der en bruker kan utføre CRUD (Create, Retrieve, Update, and Delete) operasjoner på et blogginnlegg.

Trinn 1

La oss lage en MySQL-database kalt yiitest og lage en innleggstabell i den. Tabellen vil bare ha tre kolonner: id, tittel og innhold.

LAG TABELL-innlegg (id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, tittel VARCHAR(100), innhold TEXT)

Åpne programmets konfigurasjonsfil (protected/config/main.php) og fjern kommentarer på følgende linjer:

"db"=>array("connectionString" => "mysql:host=localhost;dbname=teststasjon, "emulatePrepare" => sant, "brukernavn" => "root", "passord" => "", "charset" => "utf8",)

Erstatt testdrive med databasenavnet ditt, dvs. yiitest. Du må også gi tillatelsene som kreves av Yii for å koble til.

Steg 2

I Yii-rammeverket må hver databasetabell ha en tilsvarende modellklasse av typen CActiveRecord. Fordelen med dette er at vi ikke trenger å forholde oss direkte til databasetabellene. I stedet kan vi jobbe med modellobjekter som tilsvarer ulike tabellrader.

For eksempel er Post-klassen en modell for en meldingstabell. Et objekt i denne klassen representerer en rad fra innleggstabellen og har attributter som gjenspeiler kolonneverdiene.

For raskt å generere modellen, vil vi bruke Yii-nettverktøyet som heter gii. Dette verktøyet kan brukes til å generere modeller, kontrollere og skjemaer for CRUD-operasjoner.

For å bruke gii i prosjektet ditt, finn følgende linjer i prosjektets konfigurasjonsfil, fjern kommentarer og legg til et passord.

"gii"=>array("class"=>"system.gii.GiiModule", "password"=>passordet ditt for å få tilgang til gii, "ipFilters"=>array("127.0.0.1","::1") ,)

Ta så kontakt med gii ved å bruke følgende adresse: http://localhost/yiitest/index.php?r=gii. Hvis du bruker brukervennlige URL-er, vil adressen være: http://localhost/yiitest/gii.

Klikk på Model Generator. gii vil be deg om å skrive inn et tabellnavn; skriv inn innlegg for tabellnavnet og bruk Post for modellnavnet. Klikk deretter Generer for å lage modellen.

Sjekk mappen protected/models og du vil finne Post.php-filen der.

Trinn 3

Klikk nå på CRUD Generator. Skriv inn Post som modellnavn. Kontrollør-ID vil automatisk fylles ut som post.

Dette betyr at en ny kontroller vil bli generert under navnet PostController.php.

Klikk på Generer. En kontroller vil bli generert, samt flere visningsfiler med skjemaene som trengs for CRUD-operasjoner.

Nå har du en helt ny CRUD-applikasjon! Klikk på prøv det nå-lenken for å teste den. For å administrere meldinger må du logge på som admin/admin.

  • Oversettelse

Dette er fortsettelsen av en serie artikler viet utvikling med Entity Framework og ASP.NET MVC 3. Du finner det første kapittelet på følgende lenke: Opprette en Entity Framework-datamodell for en ASP.NET MVC-applikasjon.

I forrige leksjon laget vi en MVC-applikasjon som kan lagre og vise data ved hjelp av Entity Framework og SQL Server Compact. I denne opplæringen skal vi se på å lage og tilpasse CRUD-funksjonaliteten (opprett, les, oppdater, slett) som MVC-stillas automatisk lager for deg i kontrollere og visninger.

Merk En vanlig praksis er å implementere depotmønsteret for å lage et abstraksjonslag mellom kontrolleren og datatilgangslaget. Men det vil komme senere, i senere leksjoner (Implementering av arkivet og arbeidsenhetene).

I denne opplæringen skal du lage følgende sider:

Opprette en detaljside

Detaljsiden vil vise innholdet i Enrollements-samlingen i en HTML-tabell.

I Kontrollere\ Studentkontrollør. cs Metoden for detaljvisningen er følgende kode:

Public ViewResult Details(int id) ( Student student = db.Students.Find(id); return View(student); )
Finn-metoden brukes til å hente én Student-enhet som tilsvarer id-parameteren som er sendt til metoden. ID-verdien er hentet fra spørringsstrengen som finnes på detaljsiden for koblingen.

Åpen Visninger\ Student\ Detaljer. cshtml. Hvert felt gjengis av DisplayFor-hjelperen:

Etternavn
@Html.DisplayFor(modell => modell.Etternavn)

For å vise påmeldingslisten, legg til følgende kode etter EnrollmentDate-feltet, før den avsluttende feltsett-taggen:

Klikk på fanen Studenter og klikk på linken Detaljer.

Opprette en Lag-side

I , erstatt HttpPost Create-metodekoden:

Public ActionResult Create(Student student) ( try ( if (ModelState.IsValid) ( db.Students.Add(student); db.SaveChanges(); return RedirectToAction("Index"); ) ) catch (DataException) ( //Log feilen(legg til et variabelnavn etter DataException) ModelState.AddModelError("", "Kan ikke lagre endringer. Prøv igjen, og se systemadministratoren hvis problemet vedvarer."); ) returner Vis(student); )
Så vi legger til Student-enheten opprettet av ASP.NET MVC Model Binder til det aktuelle enhetssettet og lagrer deretter endringene i databasen. ( Modellbinder– ASP.NET MVC-funksjonalitet som gjør det enklere å jobbe med data mottatt fra skjemaet. Modellbinder konverterer skjemadata til riktige .NET Framework-datatyper og sender dem til ønsket metode som parametere. I dette tilfellet instansierer modellbinderen Student-enheten ved å bruke egenskapsverdier fra skjemasamlingen.)

Prøv-fangst-blokken er den eneste forskjellen mellom vår versjon og det som ble automatisk generert. Hvis et unntak som er arvet fra DataException fanges opp mens endringer lagres, skrives det ut en standard feilmelding. Slike feil er vanligvis forårsaket av noe eksternt i stedet for en programmeringsfeil, så brukeren blir ganske enkelt bedt om å prøve på nytt. Kode inn Visninger\ Student\ Skape. cshtml lik koden fra Detaljer. cshtml bortsett fra EditorFor og ValidationMessageFor, som brukes per felt i stedet for DisplayFor-hjelperen. Følgende kode er et eksempel:

@Html.LabelFor(modell => modell.Etternavn)
@Html.EditorFor(modell => modell.Etternavn) @Html.ValidationMessageFor(modell => modell.Etternavn)

I Skape. cshtml det er ikke nødvendig å gjøre endringer.

Klikk på fanen Studenter og på SkapeNy.

Datavalidering er aktivert som standard. Skriv inn navn og en feil dato og klikk på Opprett for å se feilen.

I dette tilfellet ser du datasjekk på klient side, implementert med bruker JavaScript. Datavalidering på serversiden er også implementert, og selv om datavalidering på klientsiden går glipp av dårlige data, vil det bli fanget opp på serversiden og et unntak vil bli kastet.

Endre datoen til den riktige, for eksempel 9/1/2005 og klikk Skape for å se en ny student på siden Indeks.

Opprette en redigeringsside

I Controllers\StudentController.cs HttpGet Edit-metoden (den uten HttpPost-attributtet) bruker Find-metoden for å hente den valgte Student-enheten. Det er ikke nødvendig å endre koden for denne metoden.

Erstatt HttpPost Edit-metodekoden med følgende kode:

Public ActionResult Edit(Student student) ( try ( if (ModelState.IsValid) ( db.Entry(student).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); ) ) catch (DataException) ( //Logg feilen (legg til et variabelnavn etter DataException) ModelState.AddModelError("", "Kan ikke lagre endringer. Prøv igjen, og se systemadministratoren hvis problemet vedvarer."); ) return View(student); )
Koden ligner på det som var i HttpPost Create-metoden, men i stedet for å legge til enheten i settet, setter denne koden en egenskap på enheten for å avgjøre om den har blitt endret. Når SaveChanges kalles, ber Modified-egenskapen Entity Framework om å opprette en SQL-spørring for å oppdatere en post i databasen. Alle kolonner i posten vil bli oppdatert, inkludert de som brukeren ikke rørte. Samtidighetsproblemer ignoreres. (Du kan lese om samtidighetsproblemer i Håndtering av samtidighet.)

Entitetstilstander og metoder for å legge ved og lagre endringer

Databasekonteksten holder styr på synkroniseringen av entiteter i minnet med tilsvarende poster i databasen, og denne informasjonen bestemmer hva som skjer når SaveChanges-metoden kalles. For eksempel, når du sender en ny enhet til Add-metoden, endres tilstanden til denne enheten til Added. Deretter, når SaveChanges-metoden kalles, starter databasekonteksten en INSERT SQL-spørring.

Tilstanden til en enhet kan defineres som:

  • La til. Enheten er ennå ikke i databasen. SaveChanges-metoden starter kjøringen av INSERT-spørringen.
  • Uendret. Ingenting skjer når SaveChanges kalles. Denne tilstanden på en enhet når den hentes fra databasen.
  • Modifisert. Entitetsegenskapsverdier har blitt endret, SaveChanges utfører en UPDATE-forespørsel.
  • Slettet. Enheten er merket for sletting, SaveChanges utfører DELETE-forespørselen.
  • Frakoblet. Entitetstilstanden spores ikke av databasekonteksten.
I skrivebordsapplikasjonen endres tilstanden automatisk. I denne typen applikasjoner, henter du en enhet og endrer verdiene til noen egenskaper, noe som får tilstanden til å endres til Modifisert. Etter å ha kalt SaveChanges, genererer Entity Framework en UPDATE SQL-spørring som bare oppdaterer de egenskapene hvis verdier er endret.

Men i en nettapplikasjon brytes algoritmen sammen fordi databasekontekstforekomsten som henter enheten blir ødelagt når siden lastes inn på nytt. Når HttpPost Edit oppstår ny forespørsel og du har en ny kontekstforekomst, så du må manuelt endre enhetstilstanden til Modifisert. Etter dette, når SaveChanges kalles, vil Entity Framework oppdatere alle kolonnene i posten i databasen, siden konteksten ikke lenger vet hvilke egenskaper som spesifikt ble endret.

Hvis du vil at oppdatering bare skal endre brukerredigerte felt, kan du på en eller annen måte lagre opprinnelige verdier(for eksempel skjulte skjemafelt), noe som gjør dem tilgjengelige når du ringer HttpPost Edit. På denne måten kan du opprette Student-enheten ved å bruke de originale verdiene, kalle Attach-metoden med den originale versjonen av enheten, oppdatere enhetsverdiene og ringe SaveChanges. For mer informasjon, se Legg til/vedlegg og Entitetsstater og Entity Framework Local Data-teamets blogginnlegg.

Kode inn Visninger\ Student\ Redigere. cshtml lik koden i Skape. cshtml, ingen grunn til å gjøre endringer.

Klikk på fanen Studenter og så til lenken Redigere.

Endre verdiene og klikk Lagre.

Opprette en sletteside

I Controllers\StudentController.cs HttpGet Delete-metoden bruker Finn-metoden for å hente den valgte Student-enheten, akkurat som Detaljer og Rediger tidligere. For å implementere din egen feilmelding når et kall til SaveChanges mislykkes, må du legge til ekstra funksjonalitet til metoden og tilsvarende visning.

Som med oppdaterings- og opprettingsoperasjonene, trenger sletteoperasjonen også to metoder. Metoden som kalles som svar på en GET-forespørsel viser brukeren en visning som lar dem bekrefte eller avbryte slettingen. Hvis brukeren bekrefter slettingen, opprettes en POST-forespørsel og HttpPost Delete-metoden kalles.

Du må legge til en try-catch-unntaksblokk i HttpPost Delete-metodekoden for å håndtere feil som kan oppstå ved oppdatering av databasen. Hvis det oppstår en feil, kaller HttpPost Delete-metoden HttpGet Delete-metoden, og sender den en parameter som indikerer feilen. HttpGet Delete-metoden genererer igjen en bekreftelsesside for sletting med feiltekst.

Erstatt HttpGet Delete-metodekoden med følgende kode for å håndtere feil:

Public ActionResult Delete(int id, bool? saveChangesError) ( if (saveChangesError.GetValueOrDefault()) ( ViewBag.ErrorMessage = "Kan ikke lagre endringer. Prøv igjen, og hvis problemet vedvarer, se systemadministratoren."; ) return View( db.Students.Find(id)); )
Denne koden tar en valgfri boolsk parameter som indikerer at det har oppstått en feil. Denne parameteren er null (false) etter å ha kalt HttpGet Delete og sann når du kaller HttpPost Delete.

Erstatt metodekoden HttpPost Delete (DeleteConfirmed) med følgende kode som utfører slettingen og håndterer feil:

Public ActionResult DeleteConfirmed(int id) ( try ( Student student = db.Students.Find(id); db.Students.Remove(student); db.SaveChanges(); ) catch (DataException) ( //Logg feilen (legg til et variabelnavn etter DataException) return RedirectToAction("Delete", new System.Web.Routing.RouteValueDictionary ( ( "id", id ), ( "saveChangesError", true ) )); ) return RedirectToAction("Index"); )
Koden returnerer den valgte enheten og kaller Fjern-metoden, som endrer enhetens tilstand til Slettet. Når SaveChanges kalles, genereres en DELETE SQL-spørring.

Hvis ytelse er en prioritet, kan du unngå unødvendige SQL-spørringer som returnerer en post ved å erstatte koden som kaller Finn og fjern-metodene:

Student studentToDelete = new Student() ( StudentID = id ); db.Entry(studentToDelete).State = EntityState.Deleted;
Med denne koden instansierer vi Student-enheten ved å bruke bare verdien primærnøkkel og definer deretter statusen til enheten som Slettet. Det er alt Entity Framework trenger for å slette en enhet.

Som nevnt sletter ikke HttpGet Delete-metoden data. Sletting av data som svar på en GET-forespørsel (eller redigering, opprettelse eller annen handling på dataene) skaper et sikkerhetshull. Til detaljert informasjon se ASP.NET MVC Tips #46 - Ikke bruk Slett lenker fordi de lager sikkerhetshull på Stephen Walthers blogg.

I Visninger\ Student\ Slett. cshtml legg til følgende kode mellom h2 og h3:

@ViewBag.ErrorMessage

Klikk på fanen Studenter og så til lenken Slett:

Klikk Slett. Indekssiden vil lastes, uten studenten vi har slettet (du vil se et eksempel på kodebehandling i en metode i Handling Concurrency-leksjonen.)

Kontroller at det ikke er noen åpne tilkoblinger til databasen

For å sikre at alle databasetilkoblinger er ordentlig lukket og ressursene de okkuperte er frigjort, må du sørge for at konteksten blir ødelagt. Så du kan finne Dispose-metoden på slutten av StudentController-klassen i StudentController Legg til etiketter

Forbindelsene mellom entiteter i modellen er en refleksjon av de relasjonelle forbindelsene mellom tabeller i databasen. Relasjonelle koblinger i tabeller implementeres gjennom primær- og fremmednøkler, koblinger i Entity-modellen basert på navigasjonsegenskapene til entiteter.

Vår prosjektdatabase har 2 tabeller: Leietakere og Leiligheter. De er beslektet av et en-til-mange forhold. Det betyr at flere leietakere kan bo i én leilighet, men én leietaker kan kun bo i én leilighet.

På kodenivå (i modellklasser) blir navigasjonsegenskaper arrays med objektreferanser.

Offentlig klasse Leilighet ( offentlig int LeilighetID ( få; sett; ) offentlig desimal ApartСost ( få; sett; ) offentlig int Apartnummer ( få; sett; ) offentlig int AntallRom ( få; sett; ) offentlig virtuell ICollection Tenants ( get; set; ) // En rekke referanser til objekter av typen Leietaker assosiert med denne forekomsten av typen Leilighet. Navigasjonsegenskap. )

En klasse blir en beholder for en annen.

Tre lastetyper

Det er tre typer koblet datainnlasting:

  • utsatt (lat);
  • haster (direkte);
  • eksplisitt.

De er forskjellige i mekanisme og ytelse.

Under primær henting laster den ingen tilknyttede data. De lastes først etter at programmereren utløser lasting gjennom navigasjonsegenskapen.

Så hvis vi prøver å laste inn data om leilighet nummer 6, vil ikke dataene om beboerne i denne leiligheten bli lastet; dette må gjøres i to forespørsler.

Private RegistrationContext db = new RegistrationContext(); // En spørring som henter en rad fra Apartments-tabellen der ApartNumber-kolonnen er satt til 6. Apartment apartment = db.Apartments.Where(n=>n.ApartNumber == 6).FirstOrDefault(); // Andre spørring som henter alle leietakerobjekter knyttet til dette leilighetsobjektet foreach (leietaker t in apartment.Tenants) ( // Handlinger med data)

Når det er en full prøve, trenger vi to løkker (en inne i den andre):

Foreach (Leilighet a i db.Apartments) ( foreach(Leietaker t in a.Tenants) ( // Bruk dataene på en eller annen måte. ) )

DbContext-klassen bruker lazy loading som standard. Derimot, lat lasting standarden vil ikke fungere hvis:

  • modellklassen er forseglet;
  • erklært med en annen tilgangsidentifikator enn offentlig;
  • Navigasjonsegenskapen er ikke erklært virtuell.

Enhver unnlatelse av å oppfylle disse betingelsene deaktiverer lat lasting, som kan gjøres eksplisitt ved å bruke følgende instruksjoner i konstruktøren av modellklassen:

Direkte nedlasting

Apartments = db.Apartments.Include(t=>t.Tenants) foreach (Leilighet a i leiligheter) ( foreach(Leietaker t in a.Tenants) ( // Use the data somehow. ) )

Selv om eksemplet ovenfor bruker to løkker, er det bare én spørring.

Det er tillatt å bruke så mange Inkluder-anrop du vil i én kjede av metoder.

Eksplisitt lasting

Ligner på lat lasting. Det fungerer på samme måte, men krever en eksplisitt lasteinstruksjon (Load-metoden). Brukes hvis lat lasting er deaktivert.

I motsetning til lat lasting, bruker eksplisitt lasting ikke egenskapene til konteksten (DbSet), men dens Entry()-metode for å få tilgang til entitetsobjektet.

Var leiligheter = db.Apartments.ToList(); foreach (Leilighet a i leiligheter) ( // Spesifiser hvor og hva vi skal laste fra. Enden av kjeden kaller Load()-metoden. db.Entry(a).Collection(t => t.Tenants). Load(); foreach( Tenant t in a.Tenants) ( // Vi gjør noe med dataene. ) )

Vær oppmerksom på "eksplisittheten" i en slik samtale.

  • .db // Kontekstobjekt.
  • .Entry(a) // Parameteren inneholder et modellobjekt.
  • .Collection(t => t.Tenants) // Samlingsmetode fordi navigasjonsegenskapen inneholder en rekke lenker. I delegat-parameteren, som indikerer navigasjonsegenskapen.
  • .Laste(); //Eksplisitt belastningsanrop.

Hvilken støvel du skal bruke

Påfør passende belastning basert på ytelseshensyn. Hvis du vet nøyaktig hvilke data som må vises, bruk lat lasting. Hvis du gir brukeren et valg om detaljene i informasjonen som vises, er utsatt det ideelle alternativet.

Lazy lasting er mye mer effektivt hvis du trenger å kontrollere hver syklus med databaseanrop. Hvis koden representerer håndtering av store objekter med flere navigasjonsegenskaper i hver, lat lasting fordi den genererer stor kvantitet spørringer kan forårsake henger.

Det er imidlertid ingen universell metode; du må teste hver applikasjon for forskjellige størrelser base, inkludert bruk av enhetstester.

Opprette en side som viser informasjon om leiligheter og beboere.

Vi skal generere visningskontrolleren og GRUD med ved hjelp av Visual Studio. For å gjøre dette, ring i Solution Explorer kontekstmenyen i mappen Controllers og velg "Add Controller".

Velg MVC 5 Controller with Views Using Entity og klikk på Add.

  • modellklasse (Leilighet);
  • kontrollernavn (ApartmentController);
  • og kontekstklasse (RegistrationContext)

Etter å ha klikket "Legg til", vil Visual Studio generere en kontroller for deg med tilsvarende handlingsmetoder CRUD- bruksanvisning. Vi må bare rette dem.

Målet vårt er siden. Som kan vise to tabeller samtidig: den første med data fra Apartmets-tabellen, den andre - data fra leietakere-tabellen knyttet til det valgte elementet fra den første tabellen.

For å gjøre dette trenger vi en samlet visningsmodell som inkluderer data fra både den første og andre tabellen. La oss lage den i mappen Visninger/VisningerModeller i fil ApartmentIndexer.cs :

Bruke System.Collections.Generic; ved hjelp av EnrollmentApp.Models; navneområde EnrollmentApp.Views.ViewsModel ( offentlig klasse ApartmentIndexer ( offentlig IEnumerable Leiligheter ( get; sett; ) // Eiendom for lagring av en samling objekter av typen Leilighet offentlig IEnumerable Leietakere ( get; set; ) // Eiendom for oppbevaring av en samling gjenstander av typen Leilighet ) )

Slik at vi kan jobbe med forrige klasse i ApartmentController , legg til en lenke til filen til den:

Bruke EnrollmentApp.Views.ViewsModel;

La oss nå redigere indeksmetoden, som viser informasjon fra to tabeller.

Offentlig klasse ApartmentController: Controller ( private RegistrationContext db = new RegistrationContext(); // GET: Apartment public ActionResult Index(int? id) ( // opprett vår samlede klasse. var IndexModel = new ApartmentIndexer(); // Fyll den med tabell elementer Apartments.IndexModel.Apartments = db.Apartments .Include(t => t.Tenants) .OrderBy(t => t.Apartnumber); if (id != null) ( ViewBag.ApartmentID = id.Value; // Fill i tilhørende samling for hver leilighet av de tilsvarende leietakerne For å sikre at det kun blir én leietaker bruker vi Enkeltmetoden // Et alternativ er å bruke SingeOrDefault IndexModel.Tenants = IndexModel.Apartments.Where(i => i. ApartmentID == id.Value).Single(). Leietakere; ) // Send containerklassen til visningen. return View(IndexModel); ) )

Denne metoden godtar id-parameteren, som genereres av koblingen i visningen. Takket være id-parameteren kan vi forstå hvilken leilighet brukeren har valgt og vise data knyttet til den.

Alt som gjenstår er å korrigere indeksvisningen ved å legge til to lenketabeller til den og vise dataene:

@model EnrollmentApp.Views.ViewsModel.ApartmentIndexer @( ViewBag.Title = "Apartments"; } !}

Indeks

@Html.ActionLink("Legg til leilighet", "Opprett")

@foreach (var element i Model.Apartments) ( }
Leilighet nummer Antall rom Pris
@Html.DisplayFor(modelItem => item.Apartnumber) @Html.DisplayFor(modelItem => item.NumberofRooms) @Html.DisplayFor(modelItem => item.ApartСost) @Html.ActionLink("Select","Index",new ( id = item.ApartmentID)) | @Html.ActionLink("Rediger", "Rediger", ny ( id=item.ApartmentID )) | @Html.ActionLink("Detaljer", "Detaljer", ny ( id=item.ApartmentID )) | @Html.ActionLink("Slett", "Slett", ny ( id=item.ApartmentID ))
@if (Model.Tenants != null) (

Beboere i denne leiligheten

@foreach (var element i Model.Tenants) ( }
Etternavn For- og mellomnavn Registreringsdato
@element.Etternavn @item.FirstAndMidName @item.RegistrationDate
}

Nå som du har startet programmet, gå til indekssiden. Siden viser en liste over leiligheter: