25. august 2012 - 22:06Der 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);
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
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 :-/// ))
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.
@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.
@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.
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.
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(); } }
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); }
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..]
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.. )
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 {
// 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();
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..
Synes godt om
Ny brugerNybegynder
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.