|
[ bigtime @ 04.03.2007. 08:20 ] @
| Pozdrav,
Treba da uradim storno u magacinu, tj. da vratim proizvode na stanje magacina. Potrebna mi je ideja kako bih mogao da u bazi Northwind vratim stanje iz tabele Order_Details (kolona 'Quantity') u tabelu Products (tabela 'UnitsInStock'). Obe kolone su smallint.
Hteo sam u tabeli Order_Details, po OrderID broju da pronadjem sve narudzbine i da iz tih narudzbina izvucem sve proizvode(ProductID) i broj kupljenih proizvoda(Quantity) i da taj broj kupljenih vratim na stanje u tabeli Products (UnitsInStock).
Potrebna mi je samo ideja kako da krenem to da radim, mislio sam da pokusam sa DataRelations, nesto sam uspeo da izvucem iz baze, ali ne znam kako dalje, mislim da sam malo promasio koncept rada...
Pozdrav,
Vlada
[Ovu poruku je menjao bigtime dana 06.03.2007. u 09:56 GMT+1] |
[ Vreljanski Milan @ 07.03.2007. 17:51 ] @
E ovako jutros krenem da ti napisem odgovor i onda mi se nesto zezne i propade mi post, ali evo sad sam zavrsio sljaku pa reko da iskuliram i da ti pomognem.
nisi rekao dali se te baze koriste za neku platformu - aplikaciju tipa VB ili C#, ako je tako onda moras napisati programski kog koji ce to da odradi.
ukoliko nije tako onda moras da napises sql upit koji ce da ti odradi taj posao
obzirom da je sad ovo SELECT CASE ja kao program ne znam kako da nastavim, pa cu ja da iskuliram a ti napisi malo vise detalja,
znaci dal to oces da uradis u nekom programu, hoces da to odradis preko neke web platforme, ili hoces samo da imas promene u bazi
poz
[ bigtime @ 08.03.2007. 14:06 ] @
Hvala na odgovoru Milane,
Prvo da odgovorim- koristim VS.NET 2003, a aplikaciju pisem u C#. Dosao sam do kraja aplikacije i ne mogu da uradim storno u bazi.
U bazi Northwind, u tabeli "Products", u koloni 'UnitsInStock' koja je smallint upisan je broj komada tog proizvoda, a u "Order_Details" tabeli, u koloni 'Quantity' upisano je koliko je kog proizvoda naruceno.
Kada zelim da storniram narudzbinu, tj. da broj narucenih proizvoda vratim na stanje u tabelu "Products", tu stanem i ne znam sta treba da radim, tj. kako da vratim te proizvode na stanje. Potreban mi je savet kako da to uradim, odnosno preko kojih kontrola mogu da uradim storniranje...
Pozdrav,
Vlada
[ vladdy @ 08.03.2007. 15:19 ] @
Malo mi je nejasno ovo storno, davno su prosle godine od Ekonomskog fakulteta :))
Odmah da ti kazem da neces pronaci "kontrolu" koja to radi nego ces morati sam da sjednes i napises mehanizam.
Pretpostavljam da pod storno mislis da musterija poruci nesto i posle otkaze i ti bi htio da sve to sto je narucio/la vratis u magacin.
Evo ti najlaksi princip i kada razmislim i nije nesto tesko.
Ides "for each" kroz tvoju narudzbu i vracas Order_Details u products nesto kao Products.UnitsInStock += Order_Details.Quantity
Posle toga obrises order ili kako ga vec ponistavas i to je to.
Ako bi ostavio kod malo bi jasnije bilo.
Postoji malo unapredjeniji mehanizam a to je da imas UNDO kao i CANCEL metode u tvom custom business object-u i ako ti to treba mogu da ti prebacim odlicnu e-knjigu " Expert C# Business Objects, Second Edition" ili " Expert VB 2005 Business Objects, Second Edition" u zavisnosti koji jezik koristis.
[ mmix @ 08.03.2007. 17:33 ] @
Citat: vladdy:
Ides "for each" kroz tvoju narudzbu i vracas Order_Details u products nesto kao Products.UnitsInStock += Order_Details.Quantity
Posle toga obrises order ili kako ga vec ponistavas i to je to.
Samo uz transactional podrsku. Ako nemas rollback mogucnost, a pukne ti kod u pola storna, ode materijalno u krivicno ;)
[ bigtime @ 08.03.2007. 18:10 ] @
Pozdrav,
Ovo sam odradio i ispisuje mi na strani tacno one podatke iz kolone 'Quantity' koje hocu da update-ujem u kolonu 'UnitsInStock'.
Prvo sam napravio 2 dataAdaptera i tabele iz oba dataAdaptera su u istom dataSet-u.
"daOrderDet": SELECT OrderID, ProductID, UnitPrice, Quantity, Discount FROM [Order Details] WHERE (OrderID = '10248')
"daProducts": SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice, Discount FROM Products
Otvorim konekciju, napunim DataSet "custDS1" i napravim DataRelation 'detailsProduct'. Povezem dve tabele "Products" i "Order_Details" i pokazem na strani podatke iz kolona 'ProductID', 'UnitsInStock' i 'Quantity'. Evo koda:
Code:
DataRelation detailsProducts;
detailsProducts = custDS1.Relations.Add("detProd",
custDS1.Tables["Products"].Columns["ProductID"],
custDS1.Tables["Order Details"].Columns["ProductID"]);
foreach (DataRow prodRow in custDS1.Tables["Products"].Rows)
{
foreach (DataRow orderRow in prodRow.GetChildRows(detailsProducts))
{
object a = prodRow["ProductID"];
object b = prodRow["UnitsInStock"];
object c = orderRow["Quantity"];
Response.Write(a + " " + b + " " + c + "<br>");
}
}
Ne znam koja je procedura kada se radi ovakav zahtev, izvukao sam na strani podatke koje cu update-ovati u bazu, ali ne znam kako dalje...
Pozdrav,
Vlada
[ vujkev @ 08.03.2007. 19:35 ] @
Možda ću ispasti glup, ali moram da pitam
Negde na ovom forumu sam pročitao da je u ovakvim programima bolje izbacivati stanje lagera kao polje u tabele već ga uvek računati kao ulaz-izlaz.
Šta je sad bolje?
Računati uvek
ili
imati stanje kao posebno polje u bazi?
[ dusans @ 08.03.2007. 20:20 ] @
Bolje je računati uvek kada ta operacija traje neznatno i to ne važi samo za ovo (stanje lagera) već i za većinu takvih stvari, ali kad imaš puno podataka ili je proračun komplikovan, onda treba razmisliti o čuvanju tog podatka u posebnoj koloni (sve to zavisi na kraju od slučaja do slučaja).
[ bigtime @ 08.03.2007. 20:27 ] @
Pozdrav,
Problem sam resio, ali ne znam da li moze tako da se ostavi da radi. Bio bih zahvalan da mi sugerisete ako ovako ne treba da se radi. Evo i koda:
Code:
//cmdUpdate = (UPDATE Products SET UnitsInStock = @pKomada WHERE (ProductID = @pID))
foreach (DataRow prodRow in custDS1.Tables["Products"].Rows)
{
foreach (DataRow orderRow in prodRow.GetChildRows(detailsProducts))
{
object a = prodRow["ProductID"];
object b = prodRow["UnitsInStock"];
object c = orderRow["Quantity"];
int b1 = int.Parse(b.ToString());
int c1 = int.Parse(c.ToString());
int d = b1 + c1;
cmdUpdate.Parameters["@pKomada"].Value = d;
cmdUpdate.Parameters["@pID"].Value = a;
sqlConnection1.Open();
cmdUpdate.ExecuteNonQuery();
sqlConnection1.Close();
}
}
Pozdrav,
Vlada
[Ovu poruku je menjao bigtime dana 08.03.2007. u 21:37 GMT+1]
[ mmix @ 08.03.2007. 22:23 ] @
Citat: vujkev: Negde na ovom forumu sam pročitao da je u ovakvim programima bolje izbacivati stanje lagera kao polje u tabele već ga uvek računati kao ulaz-izlaz.
Šta je sad bolje?
Računati uvek ili imati stanje kao posebno polje u bazi?
Ne postoji magican odgovor ovde, ali moj savet je da koristis oba od pocetka, bajtovi na disku su jeftini 
Stanje kroz agregaciju je ok, ali kad je iole veci dnevni promet artikala to postaje problem, narocito ako to stanje treba dalje da se agregira (npr, totalna vrednost sve robe maloprodajnog magacina). Imaces malo vise posla da obezbedis da suma promena od -beskonacno do +beskonacno (vremenski) bude uvek jednaka zapamcenom stanju, ali to se lako da resiti kroz serializable transakciju na nivou stored procedura koje menjaju stanje. Sa druge strane imati stanje kroz agregaciju takodje znaci moci sracunati stanje lagera u bilo kom trenutku u istoriji sto moze da bude zgodno. Dakle, ne postoji nijedan razlog da izaberes ili jedan ili drugi, uzmi oba
Citat: bigtime: Pozdrav,
Problem sam resio, ali ne znam da li moze tako da se ostavi da radi. Bio bih zahvalan da mi sugerisete ako ovako ne treba da se radi. Evo i koda:
Ovaj kod mi je malo cudan, nekako za svaki proizvod prolazi kroz sve narudzbe i postavlja stanje na vrednost iz porudzbine (to ce valjda efektivno da postavi stanje na vrednost poslednje porudzbine, ne?)
Pored toga, ovde sad imas problem o kojem sam pisao u prvom post-u, sta ako ti kod pukne na 5-oj od 10 promena. Posto nema transakcije ne mozes uraditi rollback a posto je kod puko ne mozes ga doterati do kraja i ostajes sa polu-storniranim nalogom i pogresnim stanjima na lageru..
[ vladdy @ 08.03.2007. 22:57 ] @
Citat: Problem sam resio, ali ne znam da li moze tako da se ostavi da radi. Bio bih zahvalan da mi sugerisete ako ovako ne treba da se radi. Evo i koda:
Ne znam kakav ti je nivo znanja SQL/T-SQL (pretpostavljam da se radi o mssql databazi) ali ovo ti je mnogo prakticnije rijesiti na database nivou preko stored procedure.
Tu kreiras remove_order sp i kao input prihvatis order_id i onda ce ta stored_procedure da proceslja kroz sve to i postavi kako treba. Cak mozes i da bacis custom error koji bi posle uhvatio u slucaju greske.
Nemas potrebe da to radis u .net aplikaciji osim ako si ogranicen zbog dizajn modela (imas kompletan business layer u aplikaciji) ili ti je lakse kroz datatable.rows.
Naravno, u ovom slucaju, transakcije su obavezne, mmix je to objasnio pa da ne ponavljam. apsolutno kriticno.
Onaj kod nije savrsen, moze mnogo da se refactor, ono .tostring() je veoma klimavo jer ima da ti izbaci nullexception ako naleti na null vrijednost osim naravno ako imas constraint notnull.
Ajde kada zavrsis kompletno ostavi pa ce vec neko da pogleda :)) Naravno da si testirao da radi :)
U vezi ...
Citat: vujkev: Negde na ovom forumu sam pročitao da je u ovakvim programima bolje izbacivati stanje lagera kao polje u tabele već ga uvek računati kao ulaz-izlaz.
Šta je sad bolje?
Računati uvek ili imati stanje kao posebno polje u bazi?
Slozio bi se da koristis oba ali to uvodi dozu kompleksnosti pa i nije bas za neke manje projekte.
Preko trigger-a je moguce kontrolisati da se taj units_in_stock fino regulise i racuna, znaci na svaki update/delete montiras da to izracuna i zapise u db. Cini mi se komplikovanije od "on-demand" racunanja sto opet ima udar na performance jer ako svaki put kada ti treba stanje u zalihi on preko join-a izvlaci i sabira i oduzima to moze da bude kriticno. Zavisi kako su komplikovani join i iz koliko tabela izvlaci ovo moze da bude prilicno "skupa" operacija.
Evo ti savjet, ako se cesto vrse promjene na lageru mislim da je efikasnije racunati kao ulaz-izlaz kako bi izbjegao trigger-e koji se nonstop "opaljuju" :) strucni izraz jelte.
Ako promjene nisu ceste ali zato ti treba da cesto izvlacis trenutno stanje onda je bolje da ga imas "kesiranog" u db koloni.
Ako ti treba istorija onda nemas izbora nego da ga racunas kao computed column (ulaz-izlaz) sa vremenskom promenjivom.
[ Vreljanski Milan @ 09.03.2007. 11:37 ] @
Hvala na odgovoru Milane,
Prvo da odgovorim- koristim VS.NET 2003, a aplikaciju pisem u C#. Dosao sam do kraja aplikacije i ne mogu da uradim storno u bazi.
U bazi Northwind, u tabeli "Products", u koloni 'UnitsInStock' koja je smallint upisan je broj komada tog proizvoda, a u "Order_Details" tabeli, u koloni 'Quantity' upisano je koliko je kog proizvoda naruceno.
Kada zelim da storniram narudzbinu, tj. da broj narucenih proizvoda vratim na stanje u tabelu "Products", tu stanem i ne znam sta treba da radim, tj. kako da vratim te proizvode na stanje. Potreban mi je savet kako da to uradim, odnosno preko kojih kontrola mogu da uradim storniranje...
Pozdrav,
Vlada
DataRelation detailsProducts;
detailsProducts = custDS1.Relations.Add("detProd",
custDS1.Tables["Products"].Columns["ProductID"],
custDS1.Tables["Order Details"].Columns["ProductID"]);
foreach (DataRow prodRow in custDS1.Tables["Products"].Rows)
{
foreach (DataRow orderRow in prodRow.GetChildRows(detailsProducts))
{
object a = prodRow["ProductID"];
object b = prodRow["UnitsInStock"];
object c = orderRow["Quantity"];
Response.Write(a + " " + b + " " + c + "<br>");
}
}
E vidim da si uznapredovao i to je super a kod koji si naveo radi posao, ali obzirom da imas citanje iz order details i vracanje stanja, predlazem ti da to uradis na sledeci nacin: naime order details moze imati vise stavki za koje treba da uradis storno a ako jedna ne uspe onda nisi stornirao ceo order znaci otprilike mala modifikacija tvog koda: (e da ja ovo pisem u VB... ali mislim da ce ti dati ideju, kako da to C#-jes :-D)
znaci ovu proceduru pozivas tako sto joj prosledjujes id narudzbine koju zelis da storniras
Private Sub Storniraj(sifranarudzbine as datatype sifre robe)
Imporst.system.data.sqlclient
Try
Dim Cn As SqlConnection
Cn = New SqlConnection("user id=username;password=passwor;data source=ip adresa sql servera;initial catalog=ime baze;")
Cn.Open()
Transaction = Cn.BeginTransaction(IsolationLevel.ReadCommitted)
Dim cmdOsnovno As SqlCommand = New SqlCommand("sp_CitajOrderDetails", Cn)
cmdOsnovno.CommandType = CommandType.StoredProcedure
cmdOsnovno.Parameters.Add("@sifra", sfr)
Dim rdr As SqlDataReader = cmdOsnovno.ExecuteReader()
Do While rdr.Read
Dim cmdStorno As SqlCommand = New SqlCommand("sp_Storniraj", Cn)
cmdStorno.CommandType = CommandType.StoredProcedure
cmdStorno.Parameters.Add("@roba", rdr("sifra artikla"))
cmdStanje.Parameters.Add("@kolicina", rdr("komada artikla"))
cmdStanje.Transaction = Transaction
cmdStanje.ExecuteNonQuery()
Loop
Transaction.Commit()
Catch ex As Exception
'rollback transaction
Transaction.Rollback()
MsgBox("Doslo je do greske:" & ex.Message)
Throw
Finally
cn.close
cn.dispose
End Try
End Sub
E ovo ce ti dati ideju kako dalje, izvini ako se neka greska potkrala ali sam radio copy paste nekih delova tako da da ti stvorim sliku.
E sta je poenta:
1. recimo iz neke liste uzimas sifru narudzbine koju zelis da storniras, ubacujes je ovoj proceduri
2. otvaras konekciju i vezujes je za transakciju
3. citas podatke o toj narudzbini znaci koji su artikli u njoj i koje su kolicine
4. za svaki taj podatak vezujes novu komandu koja menja kolicinu na stanju tog artikla tj radi + za taj broj
5. tu komandu vezujes za transakciju
6. kada je sve proslo ok izvrsavas transakciju i radis upis, ako je bilo sta lose proslo u upisu nema transakcije i nije uradjeno storno to hvatas kod trans rollback
7. ja koristim stored procedure, tako da u prvoj sp_citaj order details moras da napravis citanje detalja narudzbine a u drugoj sp_storno radis update tabele gde ti je kolicina
eto nadam se da pomaze, svakako bi trebalo da ides u ovom pravcu, tj da uneses u svoj kod transakciju za pocetak, a kasnije da krenes da razmisljas o daljem unapredjenju arhitekture.
poz
P.S.
ovaj problem oko racunanja + - ulaza ili ok ozapisa kolicine posebno je stvarno problem, ja koristim oba nacina, imam polje za kolicinu i njega menjam i to je dobro jer mi je manje opterecenje aplikacije, ali naravno cuvam sve + - i onda mi to sluzi za proveru.
[ bigtime @ 09.03.2007. 12:49 ] @
Pozdrav,
Znam da bi trebalo da se radi preko stored procedure, jer postoji mogucnost da se izgube podaci za vreme storniranja kao sto su se svi i slozili, samo nisam znao kako da pocnem da radim sa stored procedurom taj proces, pa se ovom prilikom zahvaljujem starijim programerima na pomoci :)
Pozdrav,
Vlada
[ mmix @ 09.03.2007. 13:04 ] @
Ja bi dalje preporucio da se transakcija koristi na nivou servera kad god je to moguce, drzati kontekst transakcije na klijentu je malo opterecujuce i usporava aplikaciju mnogo vise nego sto bi trebalo (i moralo). Sve ovo moze i jednom stored procedurom:
Code:
create procedure CustOrderStorno
(
@orderid int
)
as
begin
declare @errcnt int;
set @errcnt = 0;
set transaction isolation level serializable;
begin transaction;
update products
set UnitsInStock = UnitsInStock + [order details].Quantity
from [order details]
inner join products on [order details].productid = products.productid
where orderid = @orderid;
set @errcnt = @errcnt + @@ERROR;
-- ovde sad markiras order kod storniran, Northwind nema polje za to
set @errcnt = @errcnt + @@ERROR;
if (@errcnt = 0)
commit;
else
rollback;
end;
[ Vreljanski Milan @ 10.03.2007. 10:34 ] @
Citat: mmix: Ja bi dalje preporucio da se transakcija koristi na nivou servera kad god je to moguce, drzati kontekst transakcije na klijentu je malo opterecujuce i usporava aplikaciju mnogo vise nego sto bi trebalo (i moralo). Sve ovo moze i jednom stored procedurom:
[code]
create procedure CustOrderStorno
(
slazem se, al ja sam cenio da covek do tog koraka mora prvo da prodje transakcije u kodu, i stored proc calls iz koda, cisto malo da ovlada time, e onda lepo kao sto kazes, jedna sp i u njoj trans i cepaj sve - rastercuje kod i eliminise problem istovremenog pristupa.
[ mmix @ 10.03.2007. 12:52 ] @
Citat: Vreljanski Milan: slazem se, al ja sam cenio da covek do tog koraka mora prvo da prodje transakcije u kodu, i stored proc calls iz koda, cisto malo da ovlada time, e onda lepo kao sto kazes, jedna sp i u njoj trans i cepaj sve - rastercuje kod i eliminise problem istovremenog pristupa.
Iz tog razloga rec 'preporucio'. Nemoj ovo dozivljavati kao kritiku, nisam ja to napisao zato sto mislim da ti ne znas, nego zato sto vidim da on ne zna i nece nauciti ako mu se ne kaze.
[ Vreljanski Milan @ 12.03.2007. 10:41 ] @
Citat: mmix: Iz tog razloga rec 'preporucio'. Nemoj ovo dozivljavati kao kritiku, nisam ja to napisao zato sto mislim da ti ne znas, nego zato sto vidim da on ne zna i nece nauciti ako mu se ne kaze.
ma kakva crna kritika, bas nisam ni pomislio tako nesto, ovde smo da naucimo :-D. i pomognemo. evo sad ce covek da stornira dok se boje ne rastope ;-D
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|