Databinding Database
Børre Stenseth
Moduler>Databinding>Enkel database

Databasebinding

Hva
screen
Databinding, database

Denne modulen tar for seg i detalj hvordan vi kan kople en databasetabell mot en GUI-komponent, en DtaViewGrid. Først lager vi en enkel løsning som bare tillater å endre eksisterende records. Deretter lager vi en løsning som tillater både insetting av nye og fjerning av gamle, i tillegg til editeringsmuligheten.

Enkel skisse

Vi skal gjøre følgende:

  1. Opprette en databasetabell
  2. Lage en applikasjon
  3. Opprette et datagrid-objekt og binde dette mot databasetabellen
  4. Identifisere en SQL-setninger som henter data fra databasen og møblerer griden
  5. Lage og kople til en SQL-setning som oppdaterer databasen med de endringen brukeren har gjort
  6. Skrive noen linjer kode

Database

Først oppretter vi en databasetabell. Vi kan gjøre dette på flere måter.

Dersom vi har et eget verktøy for databaseadministrasjon, som "Microsoft SQL Server Management Studio Express", kan vi starte denne og opprette en databasekopling. For meg betyr det at jeg bruker server: "donau.hiof.no", jeg ber om "SQL Authentication", og at jeg oppgir brukerid, passord og databasenavn.

Alternativt kan vi gjøre dette direkte i Visual Studio. Vi høyreklikker på "Data Connections" og velger "Add Connection...". Veien videre er da å velge databaseserver (f.eks. "donau.hiof.no", authentisering, og database. Vi har to typer autentisering. Enten bruker vi Windows Autentisering eller SQL-autentisering. Windows autentisering brukes dersom databasebrukeren er opprettet med den bruker og det passordet som du er logget på med i windows. SQL-autentisering brukes dersom det er laget egen bruker og eget passord for databsetilgangen.

Når koplingen er opprettet og jeg finner min database (laget tidligere), oppretter jeg en ny tabell og fyller inn noen data. F.eks. ved følgende SQL-setninger.

create table personer(
person_id int primary key not null,
navn varchar(20),
adresse varchar(30)
);

insert into person(person_id,navn,adresse)
values(1,'ole','moss');
insert into person(person_id,navn,adresse)
values(2,'jens','halden');
insert into person(person_id,navn,adresse)
values(6,'kari','sarpsborg');

Da har jeg etablert datagrunnlaget og er klar for å lage et program som viser og tillater oppdateringer av disse dataene.

Programmet

Nesten alt arbeidet gjøres i Visual Studios grensesnitt- og dataset editorer. Vi lager på vanlig måte en "Windows Application" og får på vanlig måte en Form. Formen møbleres med kun ett objekt: En DataGridView. Alt annet koples opp som egenskaper ved denne.

Det neste vi gjør er å kople opp en datakilde, egenskapen "DataSource". Vi ber om "Add Project DataSource" og velger Database. Dialogen som følger er litt avhengig av forhistorien, hva vi har gjort Visual Studio på denne fronten før. Hvis vi tar det fra bunnen av blir det omtrent slik:

	New Connection.
	Vi får opp en dialogboks og velger:
	Microsoft SQL Server (SqlClient)
	Server name: donau.hiof.no
	Use SQL Authentication
	Brukernavn
	Passord
	ok

Jeg får da typisk opp "donau.borres.dbo" som connection navn. Jeg går videre, bekrefter at passordet mitt legges i en connectionstring og sparer denne som "borresConnectionString"

Så kommer jeg i en dialogboks der jeg plukker hvilke data fra min database som jeg vil bruke. Jeg velger tabellen person og aksepterer forslaget om at datasetet skal hete: "borresDataSet". Vi ser da at vi har fått kolonner i vår DatagridView og at vi har fått opprettet to nye objekter, hos meg heter de: "personBindingSource" og "personTableAdapter".

Vi editerer kolonnene og låser kolonnen med person_id slik at den ikke kan editeres. Vi går også inn på datagridView og setter egenskapen "AllowUserToAddRows" lik False.

SQL

Vi inspiserer "personTableAdapter", spesielt vil vi: "Edit queries in Datasett Designer..".

I vårt enkle tilfelle får vi opp et vindu, fila :borresDataSet.xsd, som lister opp våre datafelter og viser at det er laget en SQL-setning, Fill. Det er denne som sørger for at DataGridView blir fylt av data når programmet starter. Vi inspiserer denne, "Configure", og ser at den ikke overraskende er slik:

	SELECT person_id, navn, adresse FROM dbo.personer
	

Vi kan endre på denne hvis vi vil, men nå er vi mer interesserte i å lage en setning som kjører data andre vegen, til databasen. Vi velger "Add Query", og får noen forslag. Vi velger "Use SQL statements" og i neste fase veleger vi: "Update".

Vi får et ganske omfattende forslag til SQL_setning. For vårt vedkommende greier vi oss med noe som er litt enklere, f.eks. slik:

 UPDATE person
  SET person_id = @person_id, navn = @navn, adresse = @adresse 
  WHERE (person_id = @Original_person_id);   
  SELECT person_id, navn, adresse FROM person WHERE (person_id = @person_id)
	

Vi aksepterer at SQL-setningen får navnet:"UpdateQuery".

Merk nå at vi har to SQL-queries: "Fill" og "UpdateQuery". Disse to opptrer som metoder i objektet "personTableAdapter".

Koden

Den eneste koden vi trenger å skrive er den vi bruker til å oppdatere databasen når vinduet lukker, "Form1_FormClosing".

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace dbgridperson
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 'bsDataSet.personer' table. 
            // You can move, or remove it, as needed.
            this.personerTableAdapter.Fill(this.bsDataSet.personer);
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.bsDataSet.HasChanges())
            {
                DataSet ds = this.bsDataSet.GetChanges();
                this.bsDataSet.personer.AcceptChanges();
                DataTableReader dtr = ds.CreateDataReader();
                while (dtr.Read())
                {
                    this.personerTableAdapter.UpdateQuery(
                       Convert.ToInt32(dtr.GetValue(0)),
                       Convert.ToString(dtr.GetValue(1)),
                       Convert.ToString(dtr.GetValue(2)),
                       Convert.ToInt32(dtr.GetValue(0))
                       );
                }
            }
        }
    }
}

Vi ser at programmet vårt ikke er særlig nyttig, siden det eneste vi får lov til er å endre data for registrerte personer. Vi få verken lov til å legge inn nye eller fjerne noen.

Funksjonell løsning

Vi forbedrer løsningen med å legge inn funksjonalitet for å sette inn nye personer og for å fjerne personer.

screen

Igjen står vi overfor et ganske vanlig valg når vi skal implementere i Visual Studio: Automatikk eller håndarbeid. Denne gangen velger vi maksimal automatikk. Vi tar fatt i fila: "borresDataset.xsd" og velger "Configure" (høyre museknapp). Vi får opp en dialog boks og velger "Advanced Options...". Her bekrefter vi alle forslag. Det vi gjør er altså å lage SQL-setninger for de vanligste operasjonene, herunder sett inn og fjern.

Vi gjør noen små endringer på Form1, legger inn knapper for å fjerne og lagre, og lager et panel for innskriving av ny person.

Koden

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace dbgridperson
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            this.personTableAdapter1.Fill(this.bsDataSet.person);
         }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.bsDataSet.HasChanges())
                this.personTableAdapter1.Update(this.bsDataSet);
        }
        private void settinn_Click(object sender, EventArgs e)
        {
            panel1.Visible = true;
        }
        private void buttonRemove_Click(object sender, EventArgs e)
        {
            // update possible edits before we delete (and reload)
            if (this.bsDataSet.HasChanges())
                this.personTableAdapter1.Update(this.bsDataSet);
            // remove selected
            int ix=dataGridView1.CurrentRow.Index;
            DataGridViewRow row=dataGridView1.Rows[ix];
            int id = Convert.ToInt32(row.Cells[0].Value);
            string navn=Convert.ToString(row.Cells[1].Value);
            String adr =Convert.ToString(row.Cells[2].Value);
            String tlf = Convert.ToString(row.Cells[3].Value);
            if (MessageBox.Show(this, "Vil du virkelig fjerne: " + navn,
                                      "fjerne",MessageBoxButtons.YesNo)==
                                      DialogResult.Yes)
            {
                personTableAdapter1.Delete(id, navn, adr, tlf);
                this.personTableAdapter1.Fill(this.bsDataSet.person);
            }
        }
        private void ok_Click(object sender, EventArgs e)
        {
            // update possible edits before we insert (and reload)
            if(this.bsDataSet.HasChanges())
                this.personTableAdapter1.Update(this.bsDataSet); 
            
            String navn = textBoxNavn.Text;
            String adr = textBoxAdr.Text;
            String tlf = textBoxTlf.Text;
            Random r=new Random(DateTime.Now.Millisecond);
            int triesleft = 100;
            while (triesleft > 0)
            {
                try{
                    int id = r.Next(32167);
                    personTableAdapter1.Insert(id, navn, adr, tlf);
                    this.personTableAdapter1.Fill(this.bsDataSet.person);
                    triesleft = 0;
                }
                catch(Exception ex)
                {
                    triesleft--;
                }
            }
            panel1.Visible = false;
        }
        private void cancel_Click(object sender, EventArgs e)
        {
            panel1.Visible = false;
        }
    }
}
Referanser
  • Den enkel varianten:
    https://svn.hiof.no/svn/psource/Csharpspikes/dbgridperson
  • Den mer komplette varianten:
    https://svn.hiof.no/svn/psource/Csharpspikes/dbgridperson2
Vedlikehold

B.Stenseth, mars 2007

(Velkommen) Moduler>Databinding>Enkel database (XML)