Avatar billede jesperwerge Nybegynder
13. oktober 2007 - 12:51 Der er 15 kommentarer og
1 løsning

checkboxlist og database.

Hej Eksperter,

jeg har en hovedtabel med et ID og en anden tabel der indeholder landsdele:

Stor København
Fyn
Midt Jylland
...

denne tabel viser jeg i en CheckBoxList - selve visningen  af disse virker fint.

Jeg har en anden reference tabel hvor jeg knytter hovedtabelens ID og de valgte landsdele - nu vil jeg gerne kæde disse sammen så jeg kan vise hvilke der er valgt når jeg lister landsdele for brugeren.

eksempel:

Stor København - Checked
Syd Sjælland - Checked
Fyn - UnChecked
Sønder Jylland - Unchecked
Midt Jylland - Checked

når jeg har fået vist hvilke landsdele der er valgt, har jeg en ide om at jeg vil tjekke på om der sker ændringer ved false, true på hvert CheckBoxListItem:

int index = ChkLandsdeleListe.SelectedIndex;
        if (index > -1)
        {
            if (ChkLandsdeleListe.Items[index].Selected == true)
            {
                lblTjeck.Text = ChkLandsdeleListe.Items[index].Text.ToString() + " : true";
//insert i DB
            }
            else if (ChkLandsdeleListe.Items[index].Selected == false)
            {
                lblTjeck.Text = ChkLandsdeleListe.Items[index].Text.ToString() + " : false";
//slet fra DB
            }

Jeg er ikke sikker på at dette er den rigtige måde at opbygge DB på eller om det er for en besværlig måde at få vist valgte værdier som checked og stadig får vist den samlede landsdele liste.

/Werge
Avatar billede neoman Novice
13. oktober 2007 - 17:52 #1
Jeg kan ikke helt overskue dine tabeller - kunne du vise et eksempel med de relevante data skematisk ?

Hovedtabel
----------
HovedtabelID
..
..

Landsdelstabel
------------
LandsdelID
LandsdellNavn
Selected (Bool)

Referencetabel
-------------
RecordID
HovedtabelID
LandsdelID


Er det som ovenstående ?  Og hvad er det du ønsker at slette/inserte i db'en ?
Jeg er for så vidt ligeglad med indholdet, det er mere for at kunne forstå logikken i hvad du ønsker. Kunne du illustrere med nogle ord eller komme med et eksempel?
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 12:38 #2
hej neoman,

jeg har 3 tabeller :

hovedtabel:
hovedID
...
...

landsdeletabel: (Bruges til at styre hvilke landsdele der skal kunne vælges imellem)
landsdeleID
landsdelnavn

landsdelsreftabel: (skal indeholde de valgte landsdele pr. hovedID)
landsdelrefID
landsdeleID
hovedID

jeg vil vise en liste af landsdele fra Landsdeletabellen via checkboxlist, og vil gerne have at de landsdele der er valgt skal have flueben i. så man man sige at checked (hvis den fandtes i checkboxlist) skulle være true såfremt det står i referencetabellen.

giver det mere mening?
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 12:40 #3
landsdeæreftabellen vil have 4 records med Samme hovedID, men forskellige landsdeleID såfremt der er valgt 4 landsdele.
Avatar billede neoman Novice
14. oktober 2007 - 13:07 #4
Så vidt jeg kan se så har du to valgmuligheder.

A. Many-to-many.

Her knytter du to tabeller sammen vha en tredje. I den tredje kan du så i princippet nøjes med en composite primary key, bestående af HovedID og LandsdelID som så også er foreign keys. Med andre ord når du danner en record i Landsdelreftabel, så har du jo keys fra Hovedtabel og Landsdeltabl, og de bliver til en kombineret primær nøgle for er record i landsdelreftabel.

Landsdele
---------
landsdelID (PK)
landsdelnavn

Hovedtabel
----------
HovedID (PK)

Landsdelreftabel
----------------
LandsdelID (PK)(FK)
HovedID (PK)(FK)

B. Eftersom du har et begrænset antal landsdele, og disse ikke formodes at ændre sig, så kunne du også knytte dem sammen på en anden måde. Du kunne tilføje lidt kolonner til din Hovedtabel:

Hovedtabel:
---------------
HovedID
.
.
.
Landsdel_1  (Boolean)
Landsdel_2  (Boolean)
..
Landsdel_N  (Boolean)

Så for hver HovedID har du en række af yes/no som siger om den er valgt i den givne landsdel. Entusiaster kunne for en megastor DB tillige finde på at koge alle disse forskellige bit-kolonner ned til en enkelt int32/int64, hvori man kan gemme den samme information bit-by-bit:)
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 13:42 #5
det er helt klart A løsningen jeg vil gå efter - men det der faktisk er problemet lige nu er at få vist hele landsdelelisten fra den ene tabel, og så få dem markeret som true i checked såfremt de findes i referencetabellen. har du en ide til det loop der skal kunne håndtere dette, og hvordan ville du eventuelt opdatere reference tabellen, ville du slette alle de hidtil valgte og herefter indsætte dem alle på ny igen eller...?

/werge
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 13:45 #6
C. løsning kunne måske også være at have et felt i hovedtabellen som tekst og så skrive en comma separeret tekst med de valgte som man så kigger igennem, dog løser der stadig ikke mit problem med at få det til at blive vist korrekt - men måske det ville være lettere at overskrive et felt i hovedtabellen end at skulle hitte ud af det andet :) ???
Avatar billede neoman Novice
14. oktober 2007 - 14:20 #7
Ad C. Næppe - det er jo selv at lave arbejde som systemet kan gøre for dig (at parse noget string halløj), så det vil jeg ikke anbefale.

Det er aledeles uklart for mig hvorfor du ønsker A - men ok, kan være der er andre faktorer som spiller ind:).

Hvis du vil opdatere en "link-tabel"  for en many-to-many relation så har du to optioner:

a). Slette det hele og inserte nye links på baggrund af nye data. Det kan du gøre som du strot set selv har bekrevet i dit oprindelige spørgsmål - blot kald din kode f.eks. når brugeren trykker Done/Save eller en eller anden Next-knap. Husk blot først at loope og slette alle, og derpå loope en gang til og nu inserte alle dem som er checked.

b). Med det samme slette en landsdel hvis den blev unchecked, eller inserte den hvis den blev checked. Du kunne lave en eventhandler minCheckBoxList_SelectedIndexChanged (bare dobeltklik på din checkboxlist i Designeren) som trigges når man klikker i checkboxlisten. I handleren skal du så finde ud af om den checkbox som triggede eventet (=se hvilken værdi selectedindex har nu) nu har fået status checked=true eller false, og så med det samme fare ud i db'en og slette/tilføje den record.
Avatar billede neoman Novice
14. oktober 2007 - 14:45 #8
Nu ved jeg ikke hvilken DB du kører med, men for at sætte dine checkboxes true/false  med data fra db'en kunne du bruge noget som ligner dette:

            Dim myDBConnection As OleDbConnection = utils.DBconnection
            Dim myID As Integer

            Dim queryString As String
            queryString = ""
            Dim command As OleDbCommand = New OleDbCommand("", myDBConnection)
            command.CommandText = "SELECT profileID FROM UserProfiles WHERE userID=" & myID.ToString

            Dim mylist As CheckBoxList = DetailsView1.FindControl("CheckBoxList1")
            Dim myReader As OleDbDataReader = command.ExecuteReader

            Dim myVal As Integer
            Do While myReader.Read()
                myVal = myReader.GetInt32(0)
                For Each li As ListItem In myCehckBoxList.Items
                    If li.Value = myVal Then
                        li.Selected = True
                    End If
                Next
            Loop
            myReader.Close()
            myDBConnection.Close()
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 17:34 #9
jeg køre med en Access 2003 DB.

jeg vil lige forsøge at omskrive din VB til C# og teste det af.

/werge
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 19:08 #10
hej igen,

så lykkes det at få checkboxlisten udfyldt og få valgt dem der skulle vælges via codebehind - det er ikke den pæneste code, men det virker:

OleDbConnection MyConnection2 = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|test.mdb");
        String SelectCmd2 = "SELECT [LandsdelsID], [navn] FROM [Landsdele]";
        OleDbCommand MyCommand2 = new OleDbCommand(SelectCmd2, MyConnection2);
        MyCommand2.Connection.Open();
        OleDbDataReader result2;
        try
        {
            result2 = MyCommand2.ExecuteReader(CommandBehavior.Default);
            CheckBoxList1.DataTextField = "navn";
            CheckBoxList1.DataValueField = "LandsdelsID";
            CheckBoxList1.DataSource = result2;
            CheckBoxList1.DataBind();
        }
        catch (OleDbException exp)
        {
            throw exp;
        }
        MyCommand2.Connection.Close();

       
        OleDbConnection MyConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|test.mdb");
        String SelectCmd = "SELECT [LandsdelRefID], [LandsDelID] FROM [LandsdelRef] WHERE ParterRefID = 1";
        OleDbCommand MyCommand = new OleDbCommand(SelectCmd, MyConnection);
        MyCommand.Connection.Open();
        OleDbDataReader result;

        try
        {
            result = MyCommand.ExecuteReader();
            while (result.Read())
            {
                int myVal = result.GetInt32(1);
                foreach (ListItem li in CheckBoxList1.Items)
                {
                    if (li.Value == myVal.ToString())
                    {
                        li.Selected = true;
                    }
                }
            }
        }
        catch (OleDbException ex)
        {
            throw ex;
            //return 0;
        }
        MyCommand.Connection.Close();

nu er det bare lige det emd at få det til at virke i et formview i Editmode. har du prøvet at benytte event SelectedIndexChanged() hvor du vil finde ud af om en checkbox
er sat til true eller false?

/werge
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 19:11 #11
prøvede ovenstående kode hvor jeg udfyldte selve checkboxlisten med en almindelige GUI ObjectDataSource - men den ville ikke vælge de valgte, det var som om at den arbejde før selve checkboxlisten var udfyld, så count altid var 0.
Avatar billede neoman Novice
14. oktober 2007 - 20:04 #12
Hvis du har det hele liggende inde i et formview så er det mere logisk først at gemme ændringerne når brugeren siger OK, og dvs du skal så bare delete de gamle og inserte de nye.

Jeg har noget gammel skodkode som gør det inde i et detailsview, den må du kunne tilpasse:

    Protected Sub DetailsView1_ItemUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewUpdatedEventArgs) Handles DetailsView1.ItemUpdated
        Dim newID As Integer
        Dim myDBConnection As OleDbConnection = utils.DBconnection

        newID = DetailsView1.SelectedValue


        ' save profile by first deleting old profile and then saving the new one
        Dim queryString As String
        queryString = ""
        Dim command As New OleDbCommand(queryString, myDBConnection)
        command.CommandText = "DELETE FROM UserProfiles WHERE userID=" & newID.ToString
        '      command.Connection.Open()
        command.ExecuteNonQuery()

        Dim mylist As CheckBoxList = DetailsView1.FindControl("CheckBoxList2")
        For Each li As ListItem In mylist.Items

            If li.Selected Then
                command.CommandText = "INSERT INTO UserProfiles (userID, profileID) VALUES ('" & newID.ToString & "','" & li.Value.ToString & "')"
                command.ExecuteNonQuery()
            End If
        Next
        myDBConnection.Close()

    End Sub
Avatar billede jesperwerge Nybegynder
14. oktober 2007 - 20:13 #13
det har du nok ret i, jeg kigger nærmere på din kode

tak

/werge
Avatar billede jesperwerge Nybegynder
15. oktober 2007 - 14:07 #14
En C# version :
OleDbConnection MyConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|test.mdb");
        String DeleteCmd = "DELETE FROM [LandsdelRef] WHERE ParterRefID=" + int.Parse(lblBilID.Text);
        OleDbCommand MyCommand = new OleDbCommand(DeleteCmd, MyConnection);
        MyCommand.Connection.Open();
        try
        {
            MyCommand.ExecuteNonQuery();
        }
        catch (OleDbException exp)
        {
            throw exp;
        }

        foreach (ListItem li in ChkLandsdeleListe.Items)
        {
            if (li.Selected)
            {
                MyCommand.CommandText = "INSERT INTO LandsdelRef (ParterRefID,LandsDelID) VALUES (" + int.Parse(lblBilID.Text) +", " + li.Value + ")";
                MyCommand.ExecuteNonQuery();
            }
        }

        MyCommand.Connection.Close();
/werge
Avatar billede jesperwerge Nybegynder
15. oktober 2007 - 14:08 #15
neoman - smider du lige et svar - for det virker max.

Det er stort at du gad hjælpe mig igen, tak.

/werge
Avatar billede neoman Novice
15. oktober 2007 - 14:11 #16
okie :P
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester