PDA-applikationer med .NET: Lektion 11

Idag:
  • Lagring av data med ADO.NET: Koppling till en databas

Än så länge finns det inget ljudspår till den här lektionen.

Tänk på att lektionerna ger en översikt och introduktion. Du måste läsa i kursboken och (viktigast!) arbeta med övningarna för att tillgodogöra dig kursen.

"Bild" 1: Vad är ADO.NET?

  1. ADO = "ActiveX Data Objects"
  2. Rätt sätt att hantera data i .NET!
  3. (Bland annat) hur man kommunicerar med databaser i .NET

Bild 2: Svamparna, igen

Från lektion 9: En tillämpning som håller reda på en lista av svampar.

Tillämpningen "Svamparna" i emulatorn

"Bild" 3: En svamptabell

Tillämpningen Svamparna från lektion 9 höll bara reda på en lista med namn på svampar. Nu ska vi ha mera data om varje svamp:

Man kan göra en tabell:

Svampar
Nummer Namn Vikt Antal
1 kantarell 0.19 4
2 flugsvamp 0.43 126
3 toppslätskivling 0.22 0
5 hussvamp 13.34 7

"Bild" 4: Grundkurs om databaser

  1. En databas = en samling data
  2. En databas = en samling tabeller med data
  3. Tabellerna har namn
  4. Kolumnerna har namn
  5. Raderna har inte namn, men man kan hitta dem med hjälp av de data som finns på raden
  6. Nyckel = en kolumn (eller en kombination av kolumner) med unika värden
  7. En databashanterare = ett program som hanterar en databas

"Bild" 5: Grundkurs om SQL

Ett "programmeringsspråk" för att söka i, och uppdatera, data som finns i en databas.

Man lägger till en rad i en tabell med kommandot insert:

insert into Svampar (Nummer, Namn, Vikt, Antal)
values (6, 'tvättsvamp', 0.34, 19)

Man tar bort en eller flera rader med delete:

delete from Svampar
where Nummer = 5

Man ändrar data på en eller flera rader med update:

update Svampar set Vikt = 0.37, Antal = 20
where Nummer = 6

Man söker bland raderna med select:

select Nummer, Namn, Vikt, Antal
from Svampar
where Nummer = 2

Bild 6: Att jobba med data i ADO.NET

ADO.NET som sparar data

"Bild" 7: Två olika sätt att jobba med data i ADO.NET

"Connected approach" = uppkopplad lösning

  • Programmet är uppkopplat mot databasen hela tiden,
  • Man ändrar data i databasen allteftersom de ändras i programmet.

"Disconnected approach" = ej uppkopplad lösning

  • Programmet är inte uppkopplat mot en databas hela tiden.
  • Programmet har en särskild kopia av data, i egna tabeller.
  • Programmet kopplar upp sig mot databasen för att spara data, när det har jobbat klart.

Bild 8: Uppkopplad lösning ("tvålagerlösning")

Uppkopplad lösning i ADO.NET

Bild 9: Ej uppkopplad lösning ("trelagerlösning")

Ej uppkopplad lösning i ADO.NET

"Bild" 10: Microsoft SQL Server CE

  • En ganska liten databashanterare
  • Går att köra på själva handdatorn
  • Databasen lagras som en fil i handdatorns filsystem
  • Klarar SQL, men inte lika avancerade SQL-kommandon som till exempel Microsofts stora SQL Server
  • Följer inte med vid köpet av en Pocket PC-handdator, men finns i Visual Studio och kan installeras på handdatorn.

Bild 11: System.Data.SqlServerCE

Från början kan man inte använda SQL Server CE i sitt program, för projektet känner inte till den, och den finns inte installerad på handdatorn (eller emulatorn). Man kan inte using-deklarera System.Data.SqlServerCE:

Installation av SQL Server CE

Bild 12: Lägg till en "referens"...

Så här gör man för att lägga till System.Data.SqlServerCE i projektet, så man kan använda SQL Server CE i sitt program. Det kommer också att leda till att SQL Server CE installeras på handdatorn.

Installation av SQL Server CE

Bild 13: ...till komponenten System.Data.SqlServerCE

Installation av SQL Server CE

Bild 14: Installation av Microsoft SQL Server CE

När vi startar vår tillämpning kommer SQL Server CE att installeras på handdatorn:

Installation av SQL Server CE

Bild 15: Programmet SkapaDatabas

Programmet SkapaDatabas skapar en SQL Server CE-databas som är lämpad för att lagra en komihåg-lista. Den innehåller en enda tabell: tabellen Uppgifter.

Hela källkoden: SkapaDatabas.cs

Tillämpningen "SkapaDatabas" i emulatorn

Bild 16: Att skapa en databas från C#

Metoden knappen_Click är händelsehanterare för när man klickar på knappen Skapa databasen.

    1   using System;
    2   using System.Drawing;
    3   using System.Collections;
    4   using System.Windows.Forms;
    5   using System.Data;
    6   using System.Data.Common;
    7   using System.Data.SqlServerCe;
    8   using System.IO;
    1   private void knappen_Click(object sender, System.EventArgs e)
    2   {
    3       string db_file_name = null;
    4           string db_connection_name = null;
    5   
    6           // Skapar en databas
    7           if (File.Exists(textboxen.Text)) 
    8           {
    9                   MessageBox.Show("Filen \"" +
   10                           textboxen.Text +
   11                           "\" finns redan. Ta bort den först.");
   12           }
   13           else 
   14           {
   15                   try 
   16                   {
   17                           db_file_name = textboxen.Text;
   18                           db_connection_name =
   19                                   "Data Source=" + db_file_name;
   20                           SqlCeEngine engine = new SqlCeEngine();
   21                           engine.LocalConnectionString = db_connection_name;
   22                           engine.CreateDatabase();
   23                   }
   24                   catch (Exception ex) 
   25                   {
   26                           MessageBox.Show("Det gick inte att skapa databasen \"" +
   27                                   textboxen.Text +
   28                                   "\": " + ex.ToString());
   29                   }
   30                   
   31                   try 
   32                   {
   33                           SqlCeConnection con = new SqlCeConnection();
   34                           SqlCeCommand com = new SqlCeCommand();
   35                           con.ConnectionString = db_connection_name;
   36                           con.Open();
   37                           com.Connection = con;
   38                           com.CommandText =
   39                                   "create table Uppgifter " +
   40                                   "(Nummer integer not null primary key, " +
   41                                   "Namn nvarchar(30) not null, " +
   42                                   "Anteckningar ntext not null, " +
   43                                   "Prioritet integer not null)";
   44                           com.ExecuteNonQuery();
   45                           con.Close();
   46                           MessageBox.Show("Klart!");
   47                   }
   48                   catch (SqlCeException ex) 
   49                   {
   50                           MessageBox.Show("Misslyckades med att " +
   51                                   "skapa tabellen Uppgifter: " +
   52                                   ex.Errors[0].Message);
   53                   }
   54                   catch (Exception ex) 
   55                   {
   56                           MessageBox.Show("Misslyckades med att " +
   57                                   "skapa tabellen Uppgifter: " +
   58                                   ex.ToString());
   59                   }
   60           }
   61   }

Bild 17: Programmet KollaDatabas

Hela källkoden: KollaDatabas.cs

Tillämpningen "KollaDatabas" i emulatorn

Bild 18: Lista rader

Tillämpningen "KollaDatabas" i emulatorn

Bild 19: Att arbeta med en databas från C#: Lägg till exempelrader

    1   private void fyllknappen_Click(object sender, System.EventArgs e)
    2   {
    3           string db_file_name = inboxen.Text;
    4           string db_connection_name = "Data Source=" + db_file_name;
    5           SqlCeConnection con = new SqlCeConnection();
    6           SqlCeCommand com = new SqlCeCommand();
    7   
    8           try 
    9           {
   10                   con.ConnectionString = db_connection_name;
   11                   con.Open();
   12                   com.Connection = con;
   13                   db_insert_row(con, com, 1, "Träna", "Stenhårt!", 2);
   14                   db_insert_row(con, com, 2, "Vila", "Max 30 min", 1);
   15                   db_insert_row(con, com, 3, "Arbeta", "60h/vecka!", 3);
   16                   con.Close();
   17                   MessageBox.Show("Fyllning klar.");
   18           }
   19           catch (SqlCeException ex) 
   20           {
   21                   MessageBox.Show("Det blev nåt fel: " +
   22                                   ex.Errors[0].Message);
   23                   con.Close();
   24           }
   25   }

Bild 20: Lägg till en rad

    1   private void db_insert_row(SqlCeConnection con,
    2           SqlCeCommand com, int Nummer, string Namn,
    3           string Anteckningar, int Prioritet) 
    4   {
    5           string query = "insert into Uppgifter " +
    6                   "(Nummer, Namn, Anteckningar, Prioritet) " +
    7                   "values (" + Nummer + ", '" + Namn + "', '" +
    8                   Anteckningar + "', " + Prioritet + ")";
    9           
   10           com.CommandText = query;
   11           com.ExecuteNonQuery();
   12   }

Bild 21: Ta bort alla raderna

    1   private void tömknappen_Click(object sender, System.EventArgs e)
    2   {
    3           string db_file_name = inboxen.Text;
    4           string db_connection_name = "Data Source=" + db_file_name;
    5           SqlCeConnection con = new SqlCeConnection();
    6           SqlCeCommand com = new SqlCeCommand();
    7   
    8           try 
    9           {
   10                   con.ConnectionString = db_connection_name;
   11                   con.Open();
   12                   com.Connection = con;
   13                   com.CommandText = "delete from Uppgifter";
   14                   com.ExecuteNonQuery();
   15                   MessageBox.Show("Tömning klar.");
   16           }
   17           catch (SqlCeException ex) 
   18           {
   19                   MessageBox.Show("Det blev nåt fel: " +
   20                           ex.Errors[0].Message);
   21           }
   22           finally {
   23                   con.Close();
   24           }
   25   }

Bild 22: Ta bort en rad

Lägg till ett where-villkor i SQL-frågan:

delete from Uppgifter where Nummer = 13

Bild 23: Hämta och visa raderna

    1   private void visaknappen_Click(object sender, System.EventArgs e)
    2   {
    3           string db_file_name = inboxen.Text;
    4           string db_connection_name = "Data Source=" + db_file_name;
    5           SqlCeConnection con = new SqlCeConnection();
    6           SqlCeCommand com = new SqlCeCommand();
    7   
    8           try 
    9           {
   10                   con.ConnectionString = db_connection_name;
   11                   con.Open();
   12                   com.Connection = con;
   13                   com.CommandText =
   14                           "select Nummer, Namn, Anteckningar, Prioritet " +
   15                           "from Uppgifter";
   16                   
   17                   SqlCeDataReader reader = com.ExecuteReader();
   18                   utboxen.Text = "";
   19                   while (reader.Read())
   20                   {
   21                           string raden = reader["Nummer"] + ", " + 
   22                                   reader["Namn"] + ", ..., " +
   23                                   reader["Prioritet"] + ", " + "\r\n";
   24                           utboxen.Text += raden;
   25                   }
   26   
   27                   MessageBox.Show("Visning klar.");
   28           }
   29           catch (SqlCeException ex) 
   30           {
   31                   MessageBox.Show("Det blev nåt fel: " +
   32                           ex.Errors[0].Message);
   33           }
   34           finally 
   35           {
   36                   con.Close();
   37           }
   38   }

Läsanvisningar

Den här lektionen motsvaras av delar av kapitel 11, ADO.NET Programming. Här är några frågor som kan användas som instuderingsfrågor:
  1. ADO.NET låter oss lagra data på flera olika sätt. Vilka tre olika sätt att lagra data presenteras i kapitlet? (Tips: Svaret står redan i ingressen på s 791!)
  2. När ett program ska lagra data med hjälp av ADO.NET kan det använda antingen en uppkopplad (connected) eller en icke uppkopplad (disconnected) lösning. Den uppkopplade lösningen är hela tiden uppkopplad mot en databashanterare, medan den icke uppkopplade inte är det, men vad finns det mer för skillnader?
  3. Vad innebär felhantering (engelska: "error handling")?
  4. Varför ska man alltid ha en bra felhantering i sina program, i alla fall om de är tänkta att användas på riktigt, av riktiga användare?
  5. Mer om felhantering: Hur hanterar man de fel som uppstår i anrop till SQL Server CE?
  6. Vad är ett DataSet?
  7. Vad är en DataTable?
  8. I vilken typ av lösning (uppkopplad eller icke uppkopplad) använder man klasserna DataSet och DataTable?
  9. Hur används databindning (till kontroller) i en icke uppkopplad lösning?
  10. Vad gör metoden WriteXML? Ja, den skriver förstås XML (duh!), men när, var, vart, hur och varför?
  11. Hur skiljer sig SQL Server CE (eller, som den egentligen heter, Microsoft SQL Server 2000 Windows CE Edition) från den "vanliga" SQL Server (eller, som den egentligen heter, Microsoft SQL Server 2000)?
  12. Vilken filändelse brukar man ha på databasfiler som hör till SQL Server CE?
  13. Databashanterare brukar ha en mekanism för integritetstvillkor, på engelska "integrity constraints". Boken kallar dessa för "constraints". Vilka sådana klarar SQL Server CE av att hantera?
  14. Vad har man SqlCeEngine till?
  15. Vad har man SqlCeConnection till?
  16. Vad har man SqlCeCommand till?
  17. Vad är det för skillnad på ExecuteQuery och ExecuteNonQuery?
  18. Vad har man SqlDataReader till?

Programmeringsövningar

  1. Provkör programmet SkapaDatabas från den här lektionen, för att skapa en databas och för att installera SQL Server CE i emulatorn.
  2. Provkör programmet KollaDatabas från den här lektionen, för att fylla på exempeldata i databasen, och studera det.
  3. Skriv ett program som heter LäggInEnUppgift, som består av ett enda formulär med rutor för data om en enda komihåg-uppgift (nummer, namn, anteckningar och prioritet). Det ska också finnas en knapp, och när man trycker på den ska denna enda komihåg-uppgift läggas in i databasen. Glöm inte felhanteringen, och prova vad som händer om man försöker lägga in två rader med samma nummer.

Föregående lektion | Lektionslista | Inlämningsuppgift 3


Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se), 28 september 2007