[ Valerij Zajcev @ 22.05.2010. 13:46 ] @
Imam neki objekat u aplikaicji recimo "User{firstname, lastname, address, isvalid ...}" i u aplikaciji imam funkcionalnost izmene nekih podataka u User-u. Ono sto hocu jeste da proceduri posaljem objekat User sa svim podacima i da se izvrsi update, dakle prosledim sve parametre ime, prezime, adresa itd. ali ne zelim da se promene podaci koji nisu izmenjeni. Recimo ako sam od svega prosledjenog proceduri promenio samo adresu samo adresa treba da se updatuje. Kako se ovo izvodi? Dakle ima li neki mehanizam koji moze da proveri da li je uneti parametar drugaciji ili isti i da ne izvrsi update. Nadam se da me neko razume sta sam hteo :(
[ Valerij Zajcev @ 22.05.2010. 17:08 ] @
Imam nacin ovo d auradim iz programa. Proverim svaki property:
Code:

if (!stariKandidat.Ime.Equals(noviKandidat.Ime))
            {                
                izmene.Add("Ime", noviKandidat.Ime);
            }
...

I onda od svih promenjenih sastavim string tipa:
Code:

UPDATE t_Kandidat SET Ime = 'vladimi'

I ovako dobijem sta hocu, problem je sto mi ovo treba kao SQL procedura :(
[ stevs986 @ 22.05.2010. 23:30 ] @
Isto kao sto u aplikaciji proveravas polja, tako ih mozes proveriti i u proceduri i praviti dinamicki string koji na kraju izvrsis sa PREPARE, EXECUTE...
[ mmix @ 22.05.2010. 23:47 ] @
Neces nista ustedeti, update jednog polja je u SQLu identican update-u celog reda jer ne postoji cell-level locking, minimalna granulacija je red. Tako da slobodno pusti sva polja.

Primetices da ni dataset adapteri, ni linq, ni ef ne vode dirty flagove na nivou polja vec na nivou redova.
[ Valerij Zajcev @ 23.05.2010. 00:03 ] @
Citat:

Neces nista ustedeti, update jednog polja je u SQLu identican update-u celog reda jer ne postoji cell-level locking, minimalna granulacija je red. Tako da slobodno pusti sva polja.

Primetices da ni dataset adapteri, ni linq, ni ef ne vode dirty flagove na nivou polja vec na nivou redova.

Znaci, hoces da kazes da je u relnoj aplikaciji prihvatljivo da ako se objekat sastoji iz "ime, prezime, jmbg" i promeni se samo "jmbg" da se izvrsi update tipa:
Code:

update user
set ime = @ime, prezime = @prezime, jmbg = @jmbg
where userid = @userid

I sve se vrednosti opet upisu (iako su iste)?
Ja sam mislio da ima neka fora, ali je to mozda razlog sto guglam ceo dan bez uspeha :(
[ Boris B. @ 23.05.2010. 03:25 ] @
Citat:
Znaci, hoces da kazes da je u relnoj aplikaciji prihvatljivo da ako se objekat sastoji iz "ime, prezime, jmbg" i promeni se samo "jmbg" da se izvrsi update tipa
...
I sve se vrednosti opet upisu (iako su iste)?

Sa stanovista performansi potpuno je isto da li menjas polje ili red. Ali sa stanovista logicne konzistentnosti podataka nije isto niti pod razno, zato sto se uvek backpostuju sva polja nazad u bazu (cak i nezimenjena) sto moze da pregazi promene koje je u medjuvremenu napravio eventualni drugi korisik. Pogledaj sledeci scenario

1. Korisnik A procita Osobu (Ime, Prezime, Adresa)
2. Korisnik B procita Osobu (Ime, Prezime, Adresa)
3. Korisnik B promeni samo Adresu i zapise nazad celu Osobu
4. Korisnik A promeni samo Ime i Prezime, i napise nazad celu Osobu.

U ovom slucaju ce Korisnik A u koraku 4. pregaziti promenu Adrese, zato sto se uvek zapisuje cela osoba a ne samo promenjena polja, a korisnik A ima zastarelu vrednost polja Adresa. Zato npr. Delphi ADO wrapper to resava tako sto radi

UPDATE Osoba SET [email protected], [email protected], [email protected] WHERE [email protected] AND [email protected] AND [email protected]

Ako aplikacija ima zastarele vrednosti update failuje, tj. ne izmeni ni jedan red, sto je catchable u programu. Koliko je ovo resenje dobro je diskutabilno, pogotovo sa stanovista performansi, mada uspesno resava fantomske izmene polja nastale usled prevelike univerzalnosti DataLayer koda.

@mmix
Citat:
Primetices da ni dataset adapteri, ni linq, ni ef ne vode dirty flagove na nivou polja vec na nivou redova.

Zar datacontext u EF-u nema ObjectStateManager koji vodi promene na nivou polja entitete? Znam da sam bas to koristio za izvlacenje Diff-a izmedju starog i novog zapisa. E sad, nisam siguran da li to poŇ°tuje pri generisanju update SQL-a.
[ mmix @ 23.05.2010. 12:35 ] @
To se zove optimistic concurrency i prilicno je u upotrebi danas, cak i kad ne znas da ga koristis (auto-generated adapteri i LINQ, 99% i EF al nisam proverio, bas si me zaintrigirao sada). Realno niko ne posmatra logicki samo jedno polje niti je to (bar po meni) rezonski, ako si bazu dobro projektovao u 3NF onda su ti entiteti ispravno projektovani i onda SVA polja jedne tabele cine entitetsku celinu. Ako je promenjeno jedno od 15 polja onda to vise nije ista instanca i optimistic concurrency radi posao u sprecavanju dirty update-a. Parcijalni updati unose pretpostavke u program a znas se sta se kaze za pretpostavke, pride su indikacija da objekat/tabela nije dobro projektovana da cini neku celinu.
Sto se tice drugog pitanja, sve je to ok na aplikativnom nivou, ali iskreno sumnjam da se propagira u SQL narocito uz upotrebu optmistic locka. Ajd bas cu da probam sutra (ako ti ne probas ranije :))

@Valerij, da prihvatljivo je, sta vise pozeljno ali uz primenu gore pomenutog optimistickog locka. ako je staro i novo polje isto nista se nece promeniti, zar ne? Ne samo da nista ne stedis u lockovima, vec nista ne stedis ni u I/O jer SQL server sve jedno mora da ucita u memorijiu CEO blok u kome je tvoj red i da ceo blok snimi nazad u commitu, tako da je sve sto uspevas da izbegnes u stvari memorijski set nekog polja u kesirani page. To je sitna boranija naspram svih ostalih operacija koje su ukljucene i to jos u O(1) operaciji kao sto je update. Sta vise sanse su da ces napraviti veci performance penalty kroz svoje if/then/else strukture za svako polje.
[ Boris B. @ 24.05.2010. 12:14 ] @
@mmix
Citat:

Realno niko ne posmatra logicki samo jedno polje niti je to (bar po meni) rezonski, ako si bazu dobro projektovao u 3NF onda su ti entiteti ispravno projektovani i onda SVA polja jedne tabele cine entitetsku celinu. Ako je promenjeno jedno od 15 polja onda to vise nije ista instanca i optimistic concurrency radi posao u sprecavanju dirty update-a. Parcijalni updati unose pretpostavke u program a znas se sta se kaze za pretpostavke, pride su indikacija da objekat/tabela nije dobro projektovana da cini neku celinu.


Slazem se 99% sa tobom. E sad, za onih 1%

- Sva polja zaista cine entitetsku celinu, ali neka polja kao npr. Adresa ili Komentar su obicna opisna polja (nisu relacija) i ne uticu na entitet, zato ih svaki DL/BL layer ne bi ni proveravao ako eksplicitno ne koristi optimistic concurrency.
- Kad bi bili u nekom od Dev podforuma ne bih ni iznosio problem zastarelih vrednosti, jer to vec hendluju framework-i i built-in layeri. Ali ovde smo u MSSQL forumu gde su stvari su vise low-level i zato treba upozoriti na concurrency jer ne znamo sta covek pravi, mozda pravi svoj layer ili koristi goli SQL

[ mmix @ 24.05.2010. 13:17 ] @
Adresa u 3NF ide u zaseban objekat Adresa je entitet za sebe koji moze biti asociran sa jednim ili vise drugih entiteta (dve osobe, npr bracni parovi, iz baze mogu ziveti na istoj adresi i samim tim je promena adrese). Kontam sta hoces da kazes ali ja jednostavno ne varim parcijalni update u multi-user cak ni kad je horizontalna separacija na pod-entitete vidljiva golim okom, dakle ni za tih 1%. Ako ces sve to da uradis kaok valja, sve to mora biti dokumentovano, odrzavano i postovano od svih, i to ne samo na implementacionom vec i na dizajn nivou (npr komentar, ako jedan operater promeni licne podatke a drugi komentar da li su komentari semanticki i logicki i dalje u syncu sa korisnikom) sto je bas onako jedan opterecujuci proces za nesto sto bi trebalo resiti mozda redizajnom. Dakle nije da ne moze i nije da ne bsluzilo nekoj svrsi vec da jednostavno pravis sebi posao bez potrebe.
[ Valerij Zajcev @ 24.05.2010. 16:13 ] @
Izbacio sam proveru promena i uradio onako kako je mmix rekao. Inace evo kako izgleda to sto hocu ukratko, ovo je slika forme:

Nemojte da se cudite za Adresa1,2 i Telefon1,2 nisam hteo dalje da delim jer je 100% da nece biti vise od 1-og telefona/adrese, eto reda radi. Svi ostali podaci se nalaze u tabeli korisnika. I sada kada radim update prosledim sve podatke sa forme u objekat korisnika i njega celog u bazu tako da uvek radim update celog reda.