Windows Phone 8 Succinctly: Data Access-Storage
22
Del
to
Del
Denne Cyber Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av
Dette innlegget er en del av en serie som heter Windows Phone 8 Succinctly.Windows Phone 8 Succinctly. Kjerne ConceptsWindows Phone 8 Succinctly: Data Access-nettverk
Lokal lagring
The Internet spiller en viktig rolle i mobile applikasjoner. De fleste Windows Phone applikasjoner tilgjengelig i butikken gjøre bruk av nettverkstilkoblingen tilbys av hver enhet. Men stoler bare på nettverksforbindelsen kan være en feil; Brukerne kan befinne seg i situasjoner der ingen forbindelse er tilgjengelig. I tillegg er data planer ofte begrenset, slik at færre nettverksoperasjoner vi gjør, jo bedre brukeropplevelsen er.
Windows Phone har en spesiell måte å lagre lokale data kalles isolert lagring. Det fungerer som en vanlig filsystem, slik at du kan opprette mapper og filer som på en datamaskin harddisk. Forskjellen er at lagring er isolert med bare dine programmer kan bruke det. Ingen andre programmer kan få tilgang til lagring, og brukerne er ikke i stand til å se det når de kobler telefonen til datamaskinen. Videre, som et sikkerhetstiltak, er det isolerte lagring den eneste lagrings at søknaden kan bruke. Du har ikke lov til å få tilgang til operativsystemet mapper eller skrive data i mappen for programmet.
Lokal lagring er en av funksjonene som tilbyr dupliserte APIer-gamle Silverlight som er basert på IsolatedStorageFile klassen og den nye Windows runtime som er basert på LocalFolder klassen. Som nevnt i begynnelsen av serien, kommer vi til å fokusere på Windows Runtime APIs.
Arbeide med mapper
Basen klassen som identifiserer en mappe i lokal lagring kalles StorageFolder . Selv roten av lagring (som kan nås ved hjelp av ApplicationData.Current.LocalStorage klasse som er en del av Windows.Storage navnerom) er en StorageFolder objekt.
Denne klassen eksponerer forskjellige asynkrone metoder for å samhandle med gjeldende mappe, for eksempel:..
CreateFolderAsync () for å opprette en ny mappe i den nåværende banen
GetFolderAsync () for å få en henvisning til en undermappe av den nåværende banen
GetFoldersAsync () for å få en liste over mapper tilgjengelig i den nåværende banen.
DeleteAsync () for å slette den aktuelle mappen.
RenameAsync () for å endre navn på en mappe. < .no>
I det følgende prøve, kan du se hvordan du oppretter en mappe i lokal lagring rot:
privat async void OnCreateFolderClicked (objekt avsenderen, RoutedEventArgs e) {venter ApplicationData.Current. LocalFolder.CreateFolderAsync ("myFolder");}
Dessverre, APIene ikke har en metode for å sjekke om en mappe som allerede eksisterer. Den enkleste løsningen er å prøve å åpne mappen med GetFolderAsync () metoden og avskjære FileNotFoundException feil som er reist om mappen ikke finnes, som vist i følgende eksempel:
privat async void OnOpenFileClicked ( objekt avsenderen, RoutedEventArgs e) {StorageFolder mappe; try {mappe = avvente ApplicationData.Current.LocalFolder.GetFolderAsync ("myFolder"); } Catch (FileNotFoundException exc) {folder = null; } If (mappe == null) {MessageBox.Show ("Mappen eksisterer ikke"); }}
Arbeide med filer
filer, i stedet blir identifisert av StorageFile klasse, som på samme måte tilbyr metoder for å samhandle med filer:
DeleteAsync () for å slette en fil .
RenameAsync () for å endre navn på en fil.
CopyAsync () for å kopiere en fil fra ett sted til et annet.
MoveAsync () for å flytte en fil fra ett sted til en annen.
Utgangspunktet for å manipulere en fil er StorageFolder klassen vi har tidligere diskutert, siden det gir metoder for å åpne en eksisterende fil (GetFileAsync ()) eller for å lage en ny en i . gjeldende mappe (CreateFileAsync ())
La oss undersøke de to vanligste operasjonene. skrive innhold til en fil og lese innhold fra en fil
Hvordan lage en fil
< p> Som allerede nevnt, er første skritt å opprette en fil for å bruke Create () metoden på en StorageFolder objekt. Eksemplet nedenfor viser hvordan du oppretter en ny fil som heter file.txt i lokal lagring rot:
privat async void OnCreateFileClicked (objekt avsenderen, RoutedEventArgs e) {StorageFile file = avvente ApplicationData.Current.LocalFolder.CreateFileAsync ( "fil.txt", CreationCollisionOption.ReplaceExisting);}
Du kan også passere valgfri parameter CreationCollisionOption til metoden for å definere atferden til bruk i tilfelle en fil med samme navn allerede eksisterer. I den forrige prøven, blir ReplaceExisting verdien som brukes til å overskrive den eksisterende filen.
Nå som du har en fil referanse takket være StorageFile objekt, er du i stand til å arbeide med den ved hjelp av OpenAsync () -metoden. Denne metoden returnerer filstrøm, som du kan bruke til å skrive og lese innhold
Eksemplet nedenfor viser hvordan du skriver tekst i filen.
Privat async tomrommet OnCreateFileClicked (objekt avsenderen, RoutedEventArgs e) {StorageFile file = avvente ApplicationData.Current.LocalFolder.CreateFileAsync ("fil.txt", CreationCollisionOption.ReplaceExisting); IRandomAccessStream randomAccessStream = avvente file.OpenAsync (FileAccessMode.ReadWrite); bruker (DataWriter forfatter = ny DataWriter (randomAccessStream.GetOutputStreamAt (0))) {writer.WriteString ("Sample tekst"); avvente writer.StoreAsync (); }}
Nøkkelen er DataWriter klassen, som er en Windows Runtime klasse som kan brukes til å enkelt skrive data til en fil. Vi rett og slett nødt til å opprette et nytt DataWriter objekt, passerer som et parameter output stream på filen vi får hjelp av GetOuputStreamAt () -metoden på strømmen returnert av OpenAsync () -metoden.
DataWriter klassen byr på mange metoder for å skrive ulike typer data, som WriteDouble () for desimaltall, WriteDateTime () for datoer og WriteBytes () for binære data. I prøven vi skriver tekst med WriteString () -metoden, og da kaller vi den StoreAsync () og FlushAsync () metoder for å sluttføre skriveoperasjon
. Merk:
med
utsagn kan brukes med klasser som støtter IDisposable grensesnittet. De er vanligvis objekter som låser en ressurs inntil operasjonen er fullført, som i den foregående prøven. Inntil skrive operasjonen er ferdig, kan ingen andre metoder tilgang til filen. Med
med
uttalelse, sørger vi for at låsen frigjøres når operasjonen er fullført.
Hvordan lese en fil
Operasjonen for å lese en fil er ikke veldig forskjellig fra skrivingen en. I dette tilfellet har vi også trenger å få filstrøm bruker Openfile () -metoden. Forskjellen er at i stedet for å bruke DataWriter klassen, kommer vi til å bruke Reader klassen, som gjør det motsatte operasjonen. Se på følgende eksempelkode:
privat async void OnReadFileClicked (objekt avsenderen, RoutedEventArgs e) {StorageFile file = avvente ApplicationData.Current.LocalFolder.GetFileAsync ("fil.txt"); IRandomAccessStream randomAccessStream = avvente file.OpenAsync (FileAccessMode.Read); bruker (Reader leser = new Reader (randomAccessStream.GetInputStreamAt (0))) {uint bytesLoaded = avvente reader.LoadAsync ((uint) randomAccessStream.Size); string readString = reader.ReadString (bytesLoaded); MessageBox.Show (readString); }}
I dette tilfellet, i stedet for CreateFileAsync () metode, bruker vi GetFileAsync () -metoden, som kan brukes til å få en referanse til en allerede eksisterende fil. Deretter starter vi lesingen prosedyren ved hjelp av Datareader klassen, denne gangen ved hjelp av input stream at vi får hjelp av GetInputStreamAt () -metoden.
Som DataWriter klassen, Reader tilbyr også mange metoder for å lese ulike datatyper, som ReadDouble (), ReadDateTime (), og ReadBytes (). I dette tilfellet kan vi lese teksten vi har tidligere skrevet ved hjelp av ReadString () metoden, som krever at størrelsen på filen som parameter
en spesiell mappe. InstalledLocation
lokal lagring er den eneste lagrings vi kan bruke til å skrive vår programmets data, men i noen tilfeller kan vi trenger å ta med i vårt prosjekt noen eksisterende filer som må behandles av programmet.
Windows Runtime tilbud en API for å gi tilgang til mappen hvor programmet er installert og hvor alle filene som er en del av Visual Studio-prosjektet er kopiert. Det kalles Package.Current.InstalledLocation, og det er en del av Windows.ApplicationModel navnerom.
InstalledLocation type er StorageFolder, som mappene i lokal lagring, slik at du kan bruke de samme metoder for å arbeide med filer og mapper . Husk at du ikke vil være i stand til å skrive data, men bare lese den.
I følgende eksempel kopierer vi en fil fra mappe programmets til lokal lagring, slik at vi får skrivetilgang.
privat async void OnCopyFileClicked (objekt avsenderen, RoutedEventArgs e) {StorageFile file = avvente Package.Current.InstalledLocation.GetFileAsync ("file.xml"); avvente file.CopyAsync (ApplicationData.Current.LocalFolder);}
Merk: Under utviklingen kan det hende at du vil være i stand til å utføre skriveoperasjoner i mappen for programmet. Ikke stole på det-under sertifiseringsprosessen, er app låst, så når programmet er fordelt på Windows Phone Store er den skrivetilgang opphevet, og du vil begynne å få unntak.
Administrer innstillinger
En vanlig scenario i mobil utvikling er behovet for å lagre innstillingene. Mange programmer tilbyr en Innstillinger side der brukerne kan tilpasse ulike alternativer.
For å tillate utviklere å raskt utføre denne oppgaven, SDK inneholder en klasse kalt IsolatedStorageSettings, som tilbyr en ordbok kalt ApplicationSettings som du kan bruke til å lagre innstillinger.
Merk:
IsolatedStorageSettings
klassen er en del av de gamle lager APIer; Windows Runtime tilbyr en ny API for å administrere innstillinger, men dessverre er den ikke tilgjengelig i Windows Phone
Bruke ApplicationSettings eiendommen er svært enkel:. sin type er ordbok < streng, objekt > og den kan brukes til å lagre et objekt
I det følgende prøve, kan du se to hendelsesbehandlinger.. det første sparer en gjenstand i innstillingene, mens den andre henter det
private void OnSaveSettingsClicked (objekt avsenderen, RoutedEventArgs e) {IsolatedStorageSettings innstillinger = IsolatedStorageSettings.ApplicationSettings; settings.Add ("navn", "Matteo"); settings.Save ();} private void OnReadSettingsClicked (objekt avsenderen, RoutedEventArgs e) {IsolatedStorageSettings innstillinger = IsolatedStorageSettings.ApplicationSettings; if (settings.Contains ("navn")) {MessageBox.Show (innstillinger ["navn"] toString ().); }}
Det eneste å markere er Save () metoden, som du må ringe hver gang du ønsker å vedvare de endringene du har gjort. Med unntak av dette, det fungerer som en vanlig ordbok samling
. Merk: Under panseret, blir innstillingene lagret i en XML-fil. API tar automatisk vare på seriefunksjon og deserializing objektet du lagrer. Vi skal snakke mer om serialisering senere i denne artikkelen.
Feilsøking for Lokal lagring
En felles forutsetning for en utvikler å jobbe med lokal lagring er evnen til å se hvilke filer og mapper er faktisk lagret. Siden lagring er isolert, kan utviklere ikke bare koble telefonen til en datamaskin og utforske den.
Den beste måten å vise et program lokal lagring er å bruke et tredjepartsverktøy tilgjengelig på CodePlex kalt Windows Phone Power Tools, som tilbyr et visuelt grensesnitt for å utforske et program lokal lagring.
Verktøyet er enkelt å bruke. Etter at du har installert det, vil du være i stand til å koble til en enhet eller til en av de tilgjengelige emulatorer. Deretter, i Isolated Storage delen, vil du se en liste over alle programmene som har vært siden lastet fra Visual Studio. Hver og en vil bli identifisert med sin søknad ID (som er en GUID). Som en vanlig filutforsker, kan du utvide trestrukturen og analysere lagring innhold. Du vil være i stand til å lagre filer fra enheten til din PC, kopiere filer fra PC-en til programminne, og selv slette elementer.
Lagre Teknikker
I forrige avsnitt, diskuterte vi de grunnleggende programmeringsgrensesnitt tilgjengelig til å lagre filer og mapper i programmet. I denne delen vil vi gå dypere for å se de beste måtene å lagre programmets data, slik at den kan opprettholdes på tvers av ulike applikasjoner.
serialisering og deserialization
serialisering er den enkleste måten til å lagre et programs data i lokal lagring. Det er prosessen som omdanner komplekse objekter til vanlig tekst, slik at de kan lagres i en tekstfil ved hjelp av XML eller JSON som utgang. Deserialization er den motsatte prosessen; ren tekst konverteres tilbake til objektene slik at de kan brukes av applikasjonen.
I en Windows Phone applikasjon som bruker disse teknikkene, serialisering er vanligvis brukt hver gang programmets data endres (når et nytt element er lagt til, redigert eller fjernet) for å minimere risikoen for å miste data hvis noe skjer, som en uventet krasj eller en suspensjon. Deserialization, i stedet blir vanligvis brukt når programmet starter for første gang.
serialisering er svært enkel å bruke, men bruken bør begrenses til programmer som fungerer med små mengder data, siden alt er holdt i minne under utførelsen. Dessuten passer best scenarier der data for å spore er enkel. Hvis du har å forholde seg til mange relasjoner, databaser er trolig en bedre løsning (vi skal snakke mer om dette senere i artikkelen).
I de følgende eksempler, vi kommer til å bruke samme Person klasse vi brukte tidligere i denne serien
public class Person {public string Name {få.; sett; } Public string etternavn {får; sett; }}
Vi antar at du vil ha en samling av Person objekter, som representerer den lokale data:
List < Person > folk = new List < Person > {New Person {Name = "Matteo", etternavn = "Pagani"}, new Person {Name = "John", etternavn = "Doe"}};
serialisering
For å serial vår søknad data vi 're kommer til å bruke de lokale lagrings APIer vi lærte om i forrige avsnitt. Vi bruker Create () metoden igjen, som vist i følgende eksempel:
privat async void OnSerializeClicked (objekt avsenderen, RoutedEventArgs e) {DataContractSerializer serialisering = new DataContractSerializer (typeof (List < Person >)); StorageFile file = avvente ApplicationData.Current.LocalFolder.CreateFileAsync ("people.xml"); IRandomAccessStream randomAccessStream = avvente file.OpenAsync (FileAccessMode.ReadWrite); bruker (Stream stream = randomAccessStream.AsStreamForWrite ()) {serializer.WriteObject (stream, mennesker); avvente stream.FlushAsync (); }}
DataContractSerializer klasse (som er en del av System.Runtime.Serialization navne) tar seg av forvaltningen av serialisering prosessen. Når vi oppretter en ny forekomst, må vi spesifisere hvilken datatype vi skal serial (i forrige prøven, er det List < Person >). Deretter oppretter vi en ny fil i lokal lagring og få strømmen som trengs for å skrive data. Serialisering operasjonen er gjort ved å ringe WriteObject () metoden i DataContractSerializer klassen, som krever så parametre strømmen beliggenhet i å skrive data og objektet til serial. I dette eksempelet er det innsamling av Person objektene vi har definert tidligere.
Hvis du tar en titt på lagrings innhold med Windows Phone Power Tools, finner du en people.xml fil, som inneholder en XML-representasjon av data:
< ArrayOfPerson xmlns: I = "http://www.w3.org/2001/XMLSchema-instance~~number=plural" xmlns = "http://schemas.datacontract.org/2004/07 /Storage.Classes "> < Person > < Name > Matteo < /navn > < etternavn > Pagani < /etternavn > < /Person > < Person > < Name > John < /navn > < etternavn > Doe < /etternavn > < /Person > < /ArrayOfPerson >
Tips:
DataContractSerializer
klassen bruker XML som sin output format. Hvis du ønsker å bruke JSON i stedet, må du bruke
DataContractJsonSerializer
klasse, som fungerer på samme måte.
deserialization
deserialization prosessen er svært like og innebærer, igjen, til lager APIer lese innholdet i filen og DataContractSerializer klasse. Eksemplet nedenfor viser hvordan du deserialize dataene vi serialisert i forrige avsnitt:
privat async void OnDeserializeClicked (objekt avsenderen, RoutedEventArgs e) {StorageFile file = avvente ApplicationData.Current.LocalFolder.GetFileAsync ("people.xml "); DataContractSerializer serialisering = new DataContractSerializer (typeof (List < Person >)); IRandomAccessStream randomAccessStream = avvente file.OpenAsync (FileAccessMode.Read); bruker (Stream stream = randomAccessStream.AsStreamForRead ()) {List < Person > folk = serializer.ReadObject (stream) som List < Person >; }}
De eneste forskjellene er:
Vi får en strøm å lese ved hjelp av AsStreamForRead () -metoden
Vi bruker ReadObject () metoden i DataContractSerializer klassen. til deserialize filens innhold, som tar filstrøm som sin inngangsparameter. Det er viktig å merke seg at metoden returnerer alltid en generisk objekt, slik at du alltid må kaste det til din virkelige datatypen (i prøven, kastet vi det som List < Person >).
Ved hjelp av databaser: SQL CE
Når du utvikler komplekse applikasjoner, har du sannsynligvis til å håndtere komplekse data. Databaser er en god løsning for å håndtere denne situasjonen fordi de støtter relasjoner, og fordi hele datasettet ikke holdes i minnet, bare de nødvendige elementene er.
SQL CE er databaseløsning som ble introdusert i Windows Phone 7.5 . Det er en frittstående database, noe som betyr at data er lagret i en enkelt fil i lager uten et DBMS å administrere alle operasjonene.
Windows Phone bruker SQL CE 3.5 (den nyeste versjonen på denne tiden er 4.0, men det er ikke støttet) og støtter ikke SQL spørringen kjøres. Hver operasjon er gjort ved hjelp av LINQ til SQL, som er en av de første av Microsofts ORM løsninger
Merk:. ORM (Object-Relation Mapping) løsninger er biblioteker som er i stand til å oversette automatisk objekt operasjoner (sett inn, redigere, fjerne) til databaseoperasjoner. På denne måten kan du fortsette arbeidet på prosjektet med et objekt-orientert tilnærming. ORM vil ta seg av å skrive de nødvendige SQL-spørringer til å lagre data i databasen.
Den tilnærmingen som brukes av SQL CE på Windows Phone kalles koden først. Databasen er opprettet første gang data er nødvendig, i henhold til enhetene definisjon som du kommer til å lagre i tabeller. En annen løsning er å inkludere en allerede eksisterende SQL CE filen i Visual Studio-prosjektet. I dette tilfellet vil du bare kunne jobbe med det i skrivebeskyttet modus.
Hvordan definere Database
Det første trinnet er å lage enheter som du trenger å lagre i databasen. Hver enhet vil tilordnes en bestemt tabell.
Entity definisjon er laget ved hjelp av attributter, som er en del av System.Data.Linq.Mapping navnerom. Hver egenskap er dekorert med et attributt som vil bli brukt til å oversette den til en kolonne. I følgende eksempel tilpasser vi det kjente Person klassen skal lagres i en tabell: product: [Tabell] public class Person {[Column (IsPrimaryKey = sant, CanBeNull = false, IsDbGenerated = true)] public String Id { få; sett; } [Kolonne] offentlig string Name {får; sett; } [Kolonne] offentlig streng etternavn {får; sett; }}
Hele enheten er merket med Table attributt, mens hver eiendom er merket med Column attributt. Attributter kan tilpasses med noen egenskaper, som:
IsPrimaryKey å gjelde for kolonner som er en del av primærnøkkelen
IsDbGenerated i tilfelle kolonnen verdi må genereres automatisk hver. gang en ny rad settes inn (for eksempel en automatisk økes antall).
navn hvis du ønsker å tildele til kolonnen et annet navn enn eiendommen.
DbType å tilpasse kolonnetypen . Som standard er det kolonnetypen automatisk av eiendommens typen
Arbeide med databasen. Den Context
Context er en spesiell klasse som fungerer som et mellomledd mellom databasen og søknaden din. Det utsetter alle metodene som trengs for å utføre de vanligste operasjonene, som sette inn, oppdatere og slette.
Context klassen inneholder tilkoblingsstrengen definisjon (som er banen der databasen er lagret) og alle tabellene som er inkludert i databasen. I følgende eksempel, kan du se en Context definisjon som inkluderer Person tabellen vi har tidligere definert:
public class DatabaseContext: Context {public static string Connection = "Datakilde = isostore: /Persons.sdf"; offentlig DatabaseContext (string Connection): base (Connection) {} public Table < Person > Personer;}
En egen klasse av prosjektet arver fra Context klassen. Det vil tvinge deg til å gjennomføre en offentlig konstruktør som støtter en tilkoblingsstreng som sin inngangsparameter. Det er to tilkoblingsstrengen typer, basert på følgende prefikser:
isostore: /betyr at filen er lagret i lokal lagring. I forrige prøven, er databasen filnavn Persons.sdf og den er lagret i lagrings rot
appdata. /Betyr at filen er lagret i Visual Studio-prosjektet i stedet. I dette tilfellet, er du tvunget til å angi File Mode attributt til Read Only
public static streng Connection = "Data Source = appdata: /Persons.sdf; File Mode = Read Only";.
Til slutt kan du også kryptere databasen ved å legge et passord attributt til tilkoblingsstrengen:
public static string Connection = "Datakilde = isostore: /Persons.sdf; Password =" passord "";
Opprette Database
Så snart data er nødvendig, må du opprette databasen hvis det ikke finnes ennå. For dette formålet, utsetter Context klassen to metoder:
DatabaseExists () returnerer om databasen allerede eksisterer
CreateDatabase () skaper effektivt databasen i lagrings
..
I det følgende prøve, kan du se en typisk database initialisering som kjøres hver gang programmet starter:
private void OnCreateDatabaseClicked (objekt avsenderen, RoutedEventArgs e) {bruker (DatabaseContext db = new DatabaseContext (DatabaseContext.ConnectionString)) {if) {db.CreateDatabase () (db.DatabaseExists (!); }}}
Arbeide med data
Alle operasjoner er gjort ved hjelp av Table < T > objekt som vi har erklært i Context definisjonen. Den støtter standard LINQ operasjoner, slik at du kan spørre de data ved hjelp av metoder som Hvor (), FirstOrDefault (), Velg (), og orderby ().
I det følgende prøve, kan du se hvordan vi tar alle Personen objekter i tabellen som heter Matteo:
private void OnShowClicked (objekt avsenderen, RoutedEventArgs e) {bruker (DatabaseContext db = new DatabaseContext (DatabaseContext.ConnectionString)) {List < Person > personer = db.Persons.Where (x = > x.Name == "Matteo"). tolist (); }}
Den returnerte Resultatet kan brukes ikke bare til utstilling, men også for redigering. For å oppdatere elementet i databasen, kan du endre verdiene for den returnerte objekt ved å kalle SubmitChanges () metoden utsatt ved Context klassen
Hvis du vil legge til nye elementer i tabellen tabellen. ≪ T > klassen tilbyr to metoder: InsertOnSubmit () og InsertAllOnSubmit (). Den første metoden kan brukes til å sette inn et enkelt objekt, mens den andre legger flere elementer i en operasjon (faktisk aksepterer det en samling som et parameter).
Private void OnAddClicked (objekt avsenderen, RoutedEventArgs e ) {bruker (DatabaseContext db = new DatabaseContext (DatabaseContext.ConnectionString)) {Person person = new Person {Name = "Matteo", etternavn = "Pagani"}; db.Persons.InsertOnSubmit (person); db.SubmitChanges (); }}
Vær oppmerksom på nytt de SubmitChanges () metoden: det er viktig å kalle det hver gang du endrer tabellen (ved å legge en ny vare eller redigere eller slette en allerede eksisterende), ellers vil ikke endringene bli lagret <. br>
På samme måte kan du slette elementer ved hjelp av DeleteOnSubmit () og DeleteAllOnSubmit () metoder. I følgende eksempel, sletter vi alle personer med navnet Matteo:
private void OnDeleteClicked (objekt avsenderen, RoutedEventArgs e) {bruker (DatabaseContext db = new DatabaseContext (DatabaseContext.ConnectionString)) {List < Person > personer = db.Persons.Where (x = > x.Name == "Matteo"). tolist (); db.Persons.DeleteAllOnSubmit (personer); db.SubmitChanges (); }}
Relasjoner
I de foregående avsnittene har vi snakket om data som er lagret i en enkelt tabell. Nå er det på tide å introdusere relasjoner, som er en måte å koble sammen to eller flere tabeller. Som et eksempel, vil vi legge til en ny Order enhet i vår database, som vi vil bruke til å lagre bestillinger gjort av brukere som er lagret i Person tabellen.
Med LINQ til SQL vi vil være i stand til å :
Legg til en Person eiendom til Order enhet som lagrer en referanse til brukeren som gjort rekkefølgen
Legg til en Orders samling til Person enhet som vil inneholde alle. truffet av brukeren.
Dette gjøres ved hjelp av en fremmednøkkel, som er en egenskap deklarert i Order enhet som vil holde primærnøkkelverdi for brukeren som gjorde bestillingen.
Her er hvordan Bestill klassen ser ut: product: [Tabell] public class Bestill {[Column (IsPrimaryKey = true)] public int OrderCode {får; sett; } [Kolonne] offentlig dobbel TotalPrice {får; sett; } [Kolonne] offentlig streng ShippingAddress {får; sett; } [Kolonne] public int personId {får; sett; } Private EntityRef < Person > _Person; [Association (name = "PersonOrders", Storage = "_Person", ThisKey = "personId", OtherKey = "personId", IsForeignKey = true)] offentlig Person Person {få {return this._Person.Entity; } Satt {Person tidligereVerdi = this._Person.Entity; if (((tidligereVerdi = verdi) || (this._Person.HasLoadedOrAssignedValue == false))) {if ((tidligereVerdi = null)) {this._Person.Entity = null; previousValue.Orders.Remove (denne); } This._Person.Entity = verdi; if ((verdi = null)) {value.Orders.Add (denne); this.PersonId = value.Id; } Else {this.PersonId = standard (int); }}}}}
Det er to viktige egenskaper i klassen definisjon:
personId er fremmednøkkel, som bare holder persons ID
er en ekte person. Person objekt som, takket være Foreningen attributt, er i stand til å holde en referanse til brukeren som gjorde bestillingen. Eiendommens setter inneholder noen logikk å administrere om du legger til en ny verdi eller fjerne en allerede eksisterende.
Selvfølgelig må vi også endre Person klassen definisjonen for å håndtere relasjoner : product: [Tabell] public class Person {public Person () {_Orders = new EntitySet < Order > (); } [Column (IsPrimaryKey = sant, CanBeNull = false, IsDbGenerated = true)] public int Id {får; sett; } [Kolonne] offentlig string Name {får; sett; } [Kolonne] offentlig streng etternavn {får; sett; } Private EntitySet < Order > _Orders; [Association (name = "PersonOrders", datalagring = "_Orders", ThisKey = "personId", OtherKey = "personId", DeleteRule = "NO ACTION")] offentlig EntitySet < Order > Bestillinger {får {return this._Orders; } Satt {this._Orders.Assign (verdi); }}}
Også i denne klassen, har vi definert en ny egenskap som kalles bestillinger, hvis typen er EntitySet < T >, hvor T er den typen den andre tabellen involvert i forholdet. Takket være Association attributt, er vi være i stand til å få tilgang til alle pålegg gitt av en bruker rett og slett ved å spørre den Orders samling
I de følgende eksempler, du kan se to vanlige operasjoner hvor et forhold er involvert.: skapelse og utvalg.
private void OnAddClicked (objekt avsenderen, RoutedEventArgs e) {bruker (DatabaseContext db = new DatabaseContext (DatabaseContext.ConnectionString)) {Person person = new Person {Name = "Matteo", etternavn = " Pagani "}; Bestill orden = ny ordre {TotalPrice = 55, ShippingAddress = "Fake Street, Milan", Person = person}; db.Orders.InsertOnSubmit (rekkefølge); db.SubmitChanges (); }} private void OnQueryClicked (objekt avsenderen, RoutedEventArgs e) {bruker (DatabaseContext db = new DatabaseContext (DatabaseContext.ConnectionString)) {Bestill resultat = db.Orders.FirstOrDefault (x = > x.OrderCode == 1); MessageBox.Show (result.Person.Name); }}
Siden Person er en egenskap av ordenen klassen, det er nok til å skape en ny ordre og sette objektet som representerer brukeren som gjorde ordren som en verdi av Person eiendommen.
I samme måte, når vi får en bestilling er vi i stand til å få brukerens detaljer rett og slett ved å spørre den Person eiendommen. I forrige prøven, vi vise navnet på brukeren som gjorde bestillingen.
Oppdatere Schema
Et vanlig scenario når du planlegger å slippe en programoppdatering er at du har endret databaseskjemaet ved å legge en ny tabell eller ny kolonne, for eksempel.
SQL CE i Windows Phone tilbyr en bestemt klasse for å tilfredsstille dette kravet, kalt DatabaseSchemaUpdater, som tilbyr noen metoder for å oppdatere en allerede eksisterende databasens skjema .
Merk:
DatabaseSchemaUpdater
's formål er nettopp å oppdatere skjemaet av en allerede eksisterende database. sett; sett; sett; List < Person >