Avatar billede limes_planum Praktikant
25. august 2012 - 22:06 Der er 19 kommentarer og
1 løsning

Updaterer forkert i MsSQL'en

Jeg har rodet med det her i timevis, for at få loop'ene til at passe.

Problemet er at jeg (i dette butikssystem) har været nødsaget til at gemme kundens varer i en tabel, før jeg jeg ved afslutningen af et kundesalg (bestående af x antal varer) henter varerne i tabellen, for så at fratrække dem i en anden tabel (der så indeholder en kolonne kaldet; AntalButik (denne bliver så ændret for hvert salg, naturligt nok)).

Når jeg afvikler et salg og afslutter det, bliver antallet af vareenheder ikke fratrukket korrekt i min MsSQL? :-/

Her er koden der sammenligner de to tabeller, og burde afvikle fratrækningen korrekt:

  List<int> listTmpTabel = new List<int>();
        List<int> listIdxAntButTabel = new List<int>();
        List<int> listAntButTabel = new List<int>();

        // Denne metode indskriver varer i en tabel temporert
        public void whileLoopFraTraekVarerTmp()
        {         

            string SQLCreateCore = "";
            string SQLCreateCore0 = "";
            string SQLCreateCore2 = "";
            string SQLCreateCoreUpd = "";
            int preTmpVarLagtSam;
            int counterF = 0;
            int counterFix  =0;
            int counterS;
            int counterX = 0;
            int samTaeller = 0;
            SqlDataReader myReader = null;
            SqlDataReader myReader1 = null;
            SqlDataReader myReader2 = null;
            SqlDataReader myWriter = null;
            SqlConnection cnn = new SqlConnection("qqq");
           

            SQLCreateCore = "SELECT * FROM GerstedTmpVarer";
                cnn.Open();
                SqlCommand myCommand2 = new SqlCommand(SQLCreateCore, cnn);
                myReader = myCommand2.ExecuteReader();               

                //// Lav anden liste der derefter sammenligner
                try
                {
                    listTmpTabel.Add(0);
                    counterF = 0;
                    Console.WriteLine("counterF start= " + counterF);

                    while (myReader.Read())
                    {                       
                        Console.WriteLine("counterF= " + counterF);
                        string vareNavnTilList = Convert.ToString(myReader["tmpVar"]);

                        Console.WriteLine(vareNavnTilList);

                        //
                        preTmpVarLagtSam = Convert.ToInt32(myReader["tmpVar"]) - 100;
                        Console.WriteLine(preTmpVarLagtSam);
                        listTmpTabel.Add(preTmpVarLagtSam);

                        Console.WriteLine("listTmpTabel[" + counterFix + "]: " + listTmpTabel[counterFix]);
                        counterF += 1;
                        counterFix += 1;
                    }

                }
                catch (Exception e)
                {
                //Console.WriteLine(e);
                }
                myReader.Close();
                counterFix = 0;

            //Henter AntalButik
                    try
                    {
                        listAntButTabel.Add(0);
                        SQLCreateCore0 = "SELECT AntalButik FROM GerstedVarer2";
                        SqlCommand myCommand1 = new SqlCommand(SQLCreateCore0, cnn);
                        myReader1 = myCommand1.ExecuteReader();

                        while (myReader1.Read())
                        {                           
                            listAntButTabel.Add(Convert.ToInt32(myReader1["AntalButik"]));
                            Console.WriteLine("myReader1[AntalButik]"+myReader1["AntalButik"]);
                            Console.WriteLine("listAntButTabel[" + counterFix + "]: " + listAntButTabel[counterFix]);
                            counterFix += 1;
                        }
                       
                    }
                    catch (Exception e)
                    {
                        //Console.WriteLine(e);
                    }
                    counterF = 0;
                    counterFix = 0;
                    myReader1.Close();
                    try
                    {
                        listIdxAntButTabel.Add(0);
                        SQLCreateCore2 = "SELECT idx FROM GerstedVarer2";
                        SqlCommand myCommand4 = new SqlCommand(SQLCreateCore2, cnn);
                        myReader2 = myCommand4.ExecuteReader();

                        while (myReader2.Read())
                        {
                            listIdxAntButTabel.Add(Convert.ToInt32(myReader2["idx"]));
                            Console.WriteLine("listIdxAntButTabel[" + counterFix + "]: " + listIdxAntButTabel[counterFix]);
               
                            counterFix += 1;
                        }

                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                    counterFix= 0;
                    myReader2.Close();

       

            counterF = 0;
            cnn.Close();
            Console.WriteLine("helt ude + listIdxAntButTabel.Count: " + listIdxAntButTabel.Count);

            //Update AntalButik
            for (counterX = 0; counterX < listIdxAntButTabel.Count; counterX++)
                            {
           
                       
                        Console.WriteLine("For X -listTmpTabel.Count + counterX: " + listTmpTabel.Count + " - " + counterX);
                      try {                 

                            for (counterS = 0; counterS < listTmpTabel.Count; counterS++)
                            {
                                Console.WriteLine(" - For S - helt inde0 + [counterS]: " + counterS);
                                Console.WriteLine();

                                if (listTmpTabel[counterS] == listIdxAntButTabel[(counterX)])
                                {
                                    samTaeller += 1;                                   
                                }
                            }
                            Console.WriteLine(" - - - listTmpTabel[counterX]: " + listTmpTabel[counterX]);
                            try
                                {
                                   
                                    SqlConnection cnn2 = new SqlConnection("qqq");
                                    SQLCreateCoreUpd = "UPDATE GerstedVarer2 SET AntalButik =" + (listAntButTabel[counterX-1] - samTaeller) + "  WHERE idx =" + listTmpTabel[counterX-1] + "";
                                    cnn2.Open();
                                    Console.WriteLine("- - - - (listAntButTabel[counterX] - samTaeller): " + (listAntButTabel[counterX-1] - samTaeller));
                                    Console.WriteLine("- - - - Updater (minus 1) - listTmpTabel[counterS]");
                                    Console.WriteLine();
                                    SqlCommand myCommand3 = new SqlCommand(SQLCreateCoreUpd, cnn2);
                                    myWriter = myCommand3.ExecuteReader();
                                                                   
                                    cnn2.Close();
                             
                                }
                              catch (Exception e)
                                {
                                    Console.WriteLine(e);
                                }
                           
                        }
                        catch { }
                        samTaeller = 0;
                    }
 
            return;
            }
Avatar billede mireigi Novice
26. august 2012 - 03:44 #1
Det hele ser noget rodet ud i mine øjne, hvilket nok er grunden til, at du har problemer med at finde fejlen.

Jeg tror du skal starte med at lave systemet om eller komme med en begrundelse for, hvorfor du har været nødt til at lave systemet på den måde.
Avatar billede arne_v Ekspert
26. august 2012 - 04:20 #2
Metoden er for lang. Den boer splittes op.

Der er exception sosm bliver slugt uden at man opdager det. Ikke godt.

Mindre ting:
* der boer catches noget mindre generelt end Exception
* der boer bruges parameters
* der boer bruges using eller finally til at lukke connection
Avatar billede limes_planum Praktikant
26. august 2012 - 04:21 #3
Den her subfunktion under mit system blev (for det første) nød til at have denne skrivning-til-en-tabel, da min kvitteringsudskrivning til ekspedient-og-kunde blokerede for at jeg kunne skrive kvitteringens indhold efterfølgende til DB (altså trække dem fra).

Jeg kunne måske godt lave funktionen, alene her, bedre forfra, men dette vil kræve at der fandtes globale variabler man kunne opbevare vareantallene i.

At lave hele mit system forfra er jeg heller ikke tilhænger af da mine 5 andre topfunktioner (med hver 2-3 funktioner + dertil subfunktioner under sig) der fungerer ret godt.

Endeligt har jeg netop fået ovenstående til at virke delvist (da der bliver 'fratrukket næsten-korrekt' på nogle poster i min kolonne) - mit spørgsmål er bare;

Hvorfor koden ikke gør det konstant korrekt ved alle mine vare-poster i tabellen? (har en fornemmelse af, at jeg har stirret mig blind på loop'enes struktur, og skal bruge andre øjne til at gennemskue hvad de gør helt præcist (har ellers allerede siddet koncentreret med pen og papir for at få det bedste overblik :-/// ))
Avatar billede limes_planum Praktikant
26. august 2012 - 04:22 #4
Foregående komm. var @mireigi

@Arne: vender tilbage i morgen..
Avatar billede mireigi Novice
26. august 2012 - 12:55 #5
Jeg kunne måske godt lave funktionen, alene her, bedre forfra, men dette vil kræve at der fandtes globale variabler man kunne opbevare vareantallene i. - limes_planum

Session?
Singleton?
OOP?
Layered Programming?

Du har mange muligheder for at gemme alting i variabler eller objekter der kan tilgås globalt.
Avatar billede limes_planum Praktikant
26. august 2012 - 16:42 #6
@mireigi - meget fint.. ved hvad sessions er og har brugt det før + mere usikker på om OOP løser noget her (såfremt det betyder; Object Oriented Programming - om det er en anden forkortelse, kan jeg ikke lige gennemskue)

Så jeg lytter da bestemt til hvad du skriver, men er lidt usikker på om det gælder begge veje? Problemstillingen er ikke om jeg skal lave det forfra (som du antyder), men om det specifikke problem her kan løses eller ej (og som sagt er jeg tæt på, ved at gemme variabler i en tabel).
Kan godt være jeg lyder lidt irriteret, men jeg har en personlig dagsorden/tidsplan, som pt./indtil-videre ikke hedder; 'lave-det-forfra'.

Vil undersøge begreberne; 'Singleton' og 'Layered Programming' ved anden lejlighed, tak :)

- - -

@Arne: Har nu læst din komm. Googler mig pt. frem til, hvad du mener med dine tre punkter, da jeg er lidt kort derpå.. og vil derefter lege lidt med det før en ny komm.
Avatar billede limes_planum Praktikant
26. august 2012 - 19:38 #7
@Arne: På min mission for at finde ud af hvad der er bedst, skal jeg lige (indtil videre) høre din mening om mireigi's forskellige forslag?

Hvilke af disse vil du foreslå?
(har lidt problemer ved at se en Consol-applikation bruge Sessions, som jo bruger:
'using System.Web.SessionState;'
>> Consol == Web?
- har desuden set netop din artikel om Singleton - Singleton virker således mere til at være noget andet end for at opbevare variabel-værdier)

@mireigi: forsøger ikke at underminere dine forslag, men prøver bare at finde den hurtigste vej til en løsning :) ... og i fald Arne's forslag er lettere tilgængelige, går jeg naturligvis den vej

@Arne igen: Hælder mest til at bruge dit parameter-forslag (men er lidt på bar bund med hvad du mener der?) Pft.
Avatar billede arne_v Ekspert
26. august 2012 - 23:44 #8
Session er en web ting.

Singleton kan bruges til at opbevare vaerdier i. Men i det her tilfaelde synes jeg ikke at det er et paent design. Opgaven skal kunne loeses med helkt almindelige parametre til metoder.
Avatar billede arne_v Ekspert
26. august 2012 - 23:45 #9
Mine forslag vil ikke i sig selv loese problemet, men laver du mine rettelser, saa vil der vaere:

45% chance for at du selv kan finde fejlen
45% chance for at en af os kan finde fejlen

fordi det vil blive langt mere overskueligt.
Avatar billede limes_planum Praktikant
27. august 2012 - 23:34 #10
@Arne: Med udgangspunkt i:
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06

- har jeg flettet dette sammen:

try
                                { 
                                    // 1. declare command object with parameter
                                    SqlCommand cmd = new SqlCommand(
                                      // "select * from Customers where city = @City", conn);
                                    "UPDATE GerstedVarer2 SET AntalButik =@ButTabl WHERE idx =@ListTmp", conn);

                                    // 2. define parameters used in command object
                                    SqlParameter param = new SqlParameter();
                                    param.ParameterName = "@ButTabl";
                                    param.Value = listAntButTabel[counterX] - samTaeller;

                                    // 2b. define parameters used in command object
                                    SqlParameter paramL = new SqlParameter();
                                    paramL.ParameterName = "@ListTmp";
                                    paramL.Value = listTmpTabel[counterX];

                                    // 3. add new parameter to command object
                                    cmd.Parameters.Add(param);
                                    cmd.Parameters.Add(paramL);

                                    // get data stream
                                    myWriter = cmd.ExecuteReader();                                 
                             
                                }catch { }
                            samTaeller = 0;
                            }
                          finally{
                                    // close reader
                                    if (myWriter != null)
                                    {
                                        myWriter.Close();
                                    }

                                    // close connection
                                    if (conn != null)
                                    {
                                        conn.Close();
                                    }
                            }     

Er det hvad du mente med paramtre?
Avatar billede arne_v Ekspert
28. august 2012 - 00:38 #11
Avatar billede arne_v Ekspert
28. august 2012 - 00:41 #12
Men det vigtigste maa vaere at faa struktureret den kode.
Avatar billede arne_v Ekspert
28. august 2012 - 00:48 #13
Jeg forestiller mig noget a la:

public class VareEntry
{
    public int Id { get; set; }
    public int Antal { get; set; }
}

public List<VareEntry> HentTemp()
{
    // SELECT id,antal FROM temp
    // while loekke
}

public void OpdaterLagerMedTemp(List<VareEntry> temp)
{
    // UPDATE lager SET antal = antal - @tempantal WHERE id = @id
    foreach(VareEntry ve in temp)
    {
        // saet 2 parametre og udfoer
    }
}

public void OpdaterLager()
{
    List<VareEntry) temp = HentTemp();
    OpdaterLagerMedTemp(temp);
}
Avatar billede limes_planum Praktikant
28. august 2012 - 08:33 #14
ok - det ser ret lækkert ud - var bare lidt bange for at mine lister blev væk fra scope't da jeg lavede hele smøren i en metode.

Men en anden mere vigtig ting er at jeg andetsteds i mit system indskriver mine tmp-varer én for én:

string SQLCreateCore = "";
                    SqlDataReader myWriter = null;

                    SqlConnection cnn = new SqlConnection("Data Source=qqq");

                    //SQLCreateCore = "INSERT INTO GerstedTmpVarer (tmpVar) VALUES ('" + myCSK + "')";
                    SQLCreateCore = "INSERT INTO GerstedTmpVarer " + "(tmpVar) " + "VALUES ('" + myCSK + "')" + "SELECT @@identity";
                    cnn.Open();
                    SqlCommand myCommand1 = new SqlCommand(SQLCreateCore, cnn);
                    myWriter = myCommand1.ExecuteReader();
                    cnn.Close(); 
- - -
- hvor myCSK er et varevalg (PS: ved godt koden er sqlinjection-sårbar, men dette er et offline-consolsystem).

Varene kommer således til at blive indskrevet således, at jeg ved oprettelsen af listen (der pt sammenlignes med den anden antalbutik-liste) ikke har et antal af tmp-varer parat, og bliver derfor nød til at sammentælle dem i;

for (counterS = 0; counterS < listTmpTabel.Count; counterS++)

-loopet...

Har du evt. en smart løsning for mig der, som kan eliminere det loop (måske med en smart indskrivning til GerstedTmpVarer, som ses øverst i enkel form)?

(lige nu forestiller jeg mig en større smøre med select-tmpvar-if-not-empty-update-else-insert)

[.... Sidebemærkning: Arbejder dog pt. på at finde et sted ved 'kvitteringsoplistning for ekspedient', der alligevel kan bruges til antalsindskrivning ved GerstedTmpVarer - som nævnt i opr. sp. så var det den der ødelagde meget for mig..]
Avatar billede limes_planum Praktikant
28. august 2012 - 09:44 #15
Det begynder at lysne nu, grundet antal-indskrivning i min GerstedTmpVarer.. :)
... men bare kort

1) V/ ' public List<VareEntry> HentTemp()'

- får jeg flg. fejlmedd;

Error    44    'vareSortiTmp.whileLoopFraTraekVarerTmp()': not all code paths return a value

Skal dit 'public List<VareEntry> HentTemp()' ikke finpudses lidt?
Har ex.vis prøvet med 'void' uden held.

2) Hvordan Add'er jeg til VareEntry-listen? Da den jo ikke er en vanlig liste (.. ligner noget struct i min optik? ..)
Avatar billede limes_planum Praktikant
29. august 2012 - 08:27 #16
ok .. hører dig indirekte ->> prøver at stykke noget sammen selv herfra i stedet

v/ 1) prøver jeg at lave min egen listeopbygning

og..

v/ 2) bruger jeg en ikke helt så struct-agtig/mindre-sikker-uindkapslet fremgangsmåde

(på sigt vil jeg dog gerne have den slags ting i fingrene - men lige nu er kun fokuseret på, at få det til at virke)

- - -

I næste komm. kan det ses hvad jeg er kommet frem til (og selv om det ikke helt ligger op ad dine forslag (igen @Arne), er der point hvis min egen kode fra nu af virker.. )
Avatar billede limes_planum Praktikant
29. august 2012 - 19:10 #17
Havde en struct-opbygning til at ligge (andetsteds i systemet) jeg kunne bruge (men bliver vel bedre til at overskue tingene, og specielt hvornår en fremgangsmåde skal bruges :) ):

      public struct tmpVarItem
            {
                public int tVar;
                public int Ant;
            }

        // Denne metode indskriver varer i en tabel temporert   
            public void whileLoopFraTraekVarerTmp()
        {     
               
                List<tmpVarItem> mylist = new List<tmpVarItem>();

                SQLCreateCore = "SELECT tmpVar, Antal FROM GerstedTmpVarer";           
                cnn.Open();
                SqlCommand myCommand2 = new SqlCommand(SQLCreateCore, cnn);
                myReader = myCommand2.ExecuteReader();               

                //// Lav anden liste der derefter sammenligner!!!
                try
                {
                   
                    counterF = 0;
                    Console.WriteLine("counterF start= " + counterF);

                    while (myReader.Read())
                    {                       
                        Console.WriteLine("counterF= " + counterF);
                        string vareTilFratraek = Convert.ToString(myReader["tmpVar"]);

                        Console.WriteLine("vareTilFratraek: " + vareTilFratraek);

                       
                        preTmpVarLagtSam = Convert.ToInt32(myReader["tmpVar"]) - 100;
                        Console.WriteLine("preTmpVarLagtSam" + preTmpVarLagtSam);

                        tmpVarItem tmpVarStructObj = new tmpVarItem();
                        tmpVarStructObj.tVar = preTmpVarLagtSam;
                        tmpVarStructObj.Ant = Convert.ToInt32(myReader["Antal"]);

                        tmpVarlist.Add(tmpVarStructObj);
                        counterF += 1;
                        counterFix += 1;
                    }
                    OpdaterLagerMedTemp(tmpVarlist);
                }
                finally
                {
                    // close reader
                    if (myReader != null)
                    {
                        myReader.Close();
                    }

                    // close connection
                    if (cnn != null)
                    {
                        cnn.Close();
                    }

                }
                counterFix = 0;
               
        }
  public void OpdaterLagerMedTemp(List<tmpVarItem> tmpVarStructObjOverFoert)
        {
            conn = new SqlConnection("Dqqq");           
            conn.Open();       
                try
                                {
                                    while (tmpVarStructObjOverFoert.Count > counterX )
                                      {
                                        tmpVarItem tmpitem = (tmpVarItem)tmpVarStructObjOverFoert[counterX];               
                             
                                    // UPDATE lager SET antal = AntalButik - @tempantal WHERE id = @id                                   

                                    // 1. declare command object with parameter
                                    SqlCommand cmd = new SqlCommand(
                                      // "select * from Customers where city = @City", conn);
                                    "UPDATE GerstedVarer2 SET AntalButik = (AntalButik - @tempantal) WHERE idx =@ListTmp", conn);

                                    // 2. define parameters used in command object
                                    SqlParameter param = new SqlParameter();
                                    param.ParameterName = "@tempantal";
                                    param.Value = tmpitem.Ant;

                                    // 2b. define parameters used in command object
                                    SqlParameter paramL = new SqlParameter();
                                    paramL.ParameterName = "@ListTmp";
                                    paramL.Value = tmpitem.tVar;

                                    // 3. add new parameter to command object
                                    cmd.Parameters.Add(param);
                                    cmd.Parameters.Add(paramL);

                                    // get data stream
                                    myWriter = cmd.ExecuteReader();
                                 
                                    myWriter.Close(); 
                            }
                }
                          finally{
                                    // close reader
                                    if (myWriter != null)
                                    {
                                        myWriter.Close();
                                    }

                                    // close connection
                                    if (conn != null)
                                    {
                                        conn.Close();
                                    }
                               
                  }
            eksekverTmpTabelRensTbl();
            return;
            } 
   

        // Denne metode henter varer fra temporer tabel - for derefter at fratrække dem når betalingsform er valgt
        public void eksekverTmpTabelRensTbl()
        {
            SqlDataReader myWriter2 = null;
            SqlConnection cnn3 = new SqlConnection("qqq");
            String SQLCreateCoreFlush = "TRUNCATE TABLE GerstedTmpVarer";
            cnn3.Open();
            Console.WriteLine("Tabel truncated!");
            Console.WriteLine();
            SqlCommand myCommand3 = new SqlCommand(SQLCreateCoreFlush, cnn3);
            myWriter2 = myCommand3.ExecuteReader();
            //myWriter.Close();

            cnn3.Close();
            //counterX -= 1;               
        }
Avatar billede limes_planum Praktikant
29. august 2012 - 19:12 #18
- ingen pointuddeling :-/ .. skulle også selv "videre i teksten.."
Avatar billede arne_v Ekspert
02. september 2012 - 22:01 #19
bevares - jeg vil proeve at huske at komme "videre i teksten.." naeste gang jeg ser et spoergsmaal fra dig
Avatar billede limes_planum Praktikant
03. september 2012 - 00:06 #20
troede ikke jeg ville høre fra dig igen på spørgsmålet, og blev derfor lidt sløset omkring det, da jeg selv fandt en løsning - så kom faktisk til at give pointene til mig selv ( >> da jeg ik lige ku overskue hvordan man fortryder pointgivn., endte det med en lidt dårlig undskyldning om 'videre i teksten')

Bottom line: Hvis man ser mine andre spørgsmål, er det her ikke reglen (spørgsmålet startede også lidt skævt fra mig - en anden gang jeg har så mange linjer i et spørgsmål, vil jeg prøve at optimere først, samt præcisere bedre, udfra et bedre indledende overblik)

Nok snak - beklager, men håber på nogle guldkorn fra dig en anden gang..
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