Tema: Re: Grieztai siuo klausimu
Autorius: G.
Data: 2010-05-18 21:21:47
Kategoriška nuomonė retai būna teisinga :)

Nesutinku dėl SQLCommand ir parametrų - jie leidžia išvengti elementarių 
klaidų tokių kaip SQL injection. Maišyti kintamųjų tipus (integerius paduoti 
kaip stringus, nvarchar'us lyginti su varchar'ais ir t.t.) SQL serveriui 
irgi nėra pati geriausia įdėja, nes jis turės užsiimti visokiom konversijom, 
negalės naudoti indeksų ir panašiai.  Taip pat, parametrizuoti queriai yra 
vykdomi kitaip nei neparametrizuoti.

Tam, kad naudoti interfeisus, vieningai atidarinėti connectionus, vykdyti ir 
loginti sql komandas, visiškai nebūtina atsisakyti ADO.NET bibliotekų - 
šitie dalykai vienas kitam neprieštarauja. Gali ant ADO.NET ir DBCommand 
viršaus turėti savo abstraktesnius interfeisus, ar naudoti enteprise library 
data access bloką,  kokį nors ORM (nhybernate, linq to sql ir t.t.). Visada 
geriau naudoti kažką egzistuojančio ir populiaraus nei išradinėti savo 
dviračius, nes:
a) kitų rašytas bibliotekas testuoja ir bugus taiso kiti
b) naujai pasamdytas programeris gali mokėti ADO.NET, nhybernate, linq, bet 
tikrai nemokės naudoti jūsų inhouse framework'o.

Žinoma viską reikia pasverti ir daryti su protu, nešaudyti žvirbllių 
patrankomis, bet teigti, kad primityvus stringų dėliojimas yra visais 
atvejais geriau už ADO.NET yra ...  lame! :)


G.V.

Ps. SQL Connection'ų ir tranzakcijų patys šiais laikais niekas 
neatidarinėja - tam naudojamas TransactionScope.



"Jornada Del Muerto" <ask@me.email> wrote in message 
news:hsu1os$b9o$1@trimpas.omnitel.net...
>    Visada buvau didziausias priesininkas visokiu ADODC ir ADO.NET 
> parametru kishimu per SqlCommand... Niekad nenaudoju tokiu dalyku ir 
> visada keikiu programeri jei kieno nors kode randu sukishtus parametrus i 
> komanda o nepaduodama tiesiog tekstine uzklausa... Tiesiog dar client side 
> prisideda tada kruva pribambasu kurie speju ir uzletina...
>
>    Nors Microsoft stiliuje visada viska daryti kad veiktu leciau...
>
>    1. Tai idijotizmas ir pasidarymas sau paciam daugiau darbo, tuo paciu 
> ir pasiekimas rezultato leciau, ko pasekoje toki programuotoja vertinciau 
> kaip dirbanti neefektyviai ir galima sakyt apgaudinejanti darbdavi del to 
> kad jis koduoja 2 kart leciau jei daug kreipimusi i SQL..., pvz. small 
> query mano metodika:\
>
>
>    string id = "100"; // DB jis int, bet man jokio skirtumo, toks kodas 
> nelush jei DB si lauka pakeisiu i uniqueidentifier ar i dar kazka kito
>    // Savo programoje tiesiog nesigilinu kas yra id nes man neteks 
> analizuoti konkrecios reiksmes, tai tik identifikatorius ir man visiskai 
> nerupi kas jame
>    // tikrinimas tik nebet ar ne tuscias atvejais naudojant pvz tusciam 
> "0" bet tai anokia problema
>    string name = "Lamer";
>    string description = "Usage of DbCommand parameters is lame";
>
>    // Jei parametrai keli kaip pas mane naudoji si metoda:
>    string sql = "Insert Into TblLamers (refId, name, description) Values 
> ('"+id+"','"+name+"','"+description+"')";
>    // i parametra o ne is kart naudojamas stringas tam kad prireikus ji 
> eitu i outputa isvedinet jei to nedaro pats db lib'as kas nemaiso
>    Debug.Print(sql);
>    // Viduje Execute metodo komanda su uzklausa kaip stringu
>    db.Execute(sql);
>
>
>    Jei naudoji string.Format tai turiu patarima kist i atskira resursu 
> faila nuo sistemos kurimo pradzios visas uzklausas, tada ju neprireiks 
> ieskoti istisai per koda o viskas bus vienoj vietoj, ipac jei bus 
> teisingas namingas, daleiskim resursuose mes turim:
>
>    LamersNew  = Insert Into TblLamers (refId, name, description) Values 
> ('{0}','{1}','{2}')
>
>    Darom:
>
>    string.Format ( Resources.SQLQueries.LamersNew,
>        id,  // - Cia dar gali buti kazkokia tai tipu ar biznio logikos 
> validacija ar dar kazkas kaip pvz ivedamos informacijos SQL kabuciu 
> tikrinimas ir t.t... jei tai ejo is UI
>        name,
>        description);
>
>
>    Pavaizduotam sample labai pravers isugdyti 2 iprociai:
>        A. Viska queryje padavineti kabutese net ir integerius  - isvengsi 
> bugo kad kadanors netycia neuzdejai kabuciu, o sql tai suveiks vistiek...
>        B. Tureti iproti visada naudoti tam tikra eiliskuma, pvz id laukas 
> visada 1, name visada 2, desc visada 3, na ir visi kiti laukai svarbumo 
> tvarka eina is eiles, tada lieka apsispresti del vieningo ref (rysiu) 
> lauku naudojimo ar jie eina po primary kei visada ar po visos kitos info..
>
>    Esme visada naudoti vieninga sistema, 10, jei prireiks ir 50 metu...
>
>
>    2. Kisant komandos parametrus reik nurodinet ju tipa ir tada tu sudarai 
> salygas tavo pacio isgimdytiem tokiu budu exception'am nes priskiriant 
> parametra neduok dieve int tu paduosi kaip teksta ar dar kazka ne taip, tu 
> pridarai kruvas laikrodiniu bombu tokiu budu savo kode, ne del to kad 
> nesuveiks kazkas ant serverio bet del to kad tavo programa su vidine 
> validacija luzines kaip kazin kas jei truks apdairumo...
>
>    Teke uzsirauti ant vienos sistemos kur taip buvo sukoduota su jais, 
> exceptionus visus jis pakavojas buvo tai atrode viskas gerai o 20% 
> uzklausu tiesiog luzdavo del to kad jis naudojo komanda ir sukisdavo per 
> ja parametrus
>
>    3. Reiketu saudyti tokius kurie savo kode kiekviena kart atlieka visa 
> DBCommand inicializacija bet kurio kreipimosi i DB metu, nenaudojami jokio 
> savo libo ar funkcijos tam:
>
>    Viens dalykas taip didini bugu kruva, del copy-pastinamo tonu kodo, 
> antras dalykas taip neina tureti vieningos loginimo ar analizavimo (pvz. 
> performance) sistemos, trecias dalykas padarai daug kodo is nieko ir 
> pasidarai sau daug daugiau darbo ir aplamai 11 dievo isakymas - kuo 
> daugiau kodo tuo daugiau bugu.. (VISADA!)
>
>    O jei dar ir visa COnnection kiekviena kart programmeris inicializuoja, 
> ji siulyciau leta mirtim pribaigt, kas jei kazkas pasikeis po to? begiosi 
> per visa sistema kur bus 1000+ uzklausu jas perdarinedamas ?
>
>    Jei jau taip tingima pasirasyt iki galo normalu liba, pasidarykit kazka 
> tokio:
>
>    class AntiLamerism {
>
>        public static SqlCommand CreateCommand ()
>        {
>            // komandos inito kodas
>        }
>
>        public static SqlCommand CreateCommand (string sql)
>        {
>            // komandos inito kodas
>        }
>    }
>
>
>    Ir vien nuo tokios smulkmenos jusu kodas taps daug labiau 
> suprantamesnis vietoj 3-4 eiluciu turesit visada viena tam...
>
>
>    SqlCommand cmd = AntiLamerism.CreateCommand(sql);
>
>    Siaip as linkes nenaudoti konkrecios ADO.NET implementacijos o dirbti 
> interfeisu ar as lygyje, tai yra ne su SqlCommand o su DbCommand 
> abstrakcia klase arba IDbCommand interfeisu (SqlCommand kaip ir 
> OleDbCommand ar OdbcCommand ar bet kokio kito ADO.NET connectoriaus kad ir 
> oracle ir t.t.. *Command)  yra nuo jo veldeta ir daznai nereikalinga jokia 
> konkretizacija
>
>    Nors galima pasirasyti visa DB klase tam, kuri turetu ir klaidu 
> tikrinima ir net daug kitu pagalbiniu dalyku, jei idomu galite mano 
> straipsni paskaityti: 
> http://www.lythum.lt/content/adonet-programavimas-naudojant-interfeisus 
> (pavizdys rasytas is galvos, pas mane tiesa yra veikianti sistema, 
> veikianti ir grubiam lygyje ir net su oleDB schemu apdirbimu bet jis (C) 
> ir nebus publikuojamas, del to duotas tik netasytas prototipas kuri norint 
> panaudoti teks suprasti ka kodas daro) tiesa puslapis veliau bus 
> greiciausia visiskai perdarytas del to konkretus linkas po keliu menesiu 
> gali nustot veikti.
>
>
> Su tipisku jam inirsiu,
> JDM.
>
>
> "Meff" <noemail@japan.cc> wrote in message 
> news:hs9agt$qek$1@trimpas.omnitel.net...
>> Sveiki. Įdomumo dėlei (M$ nelabai kažką radau, o StackOverflow aiškina 
>> apie konvertavimą į konkretų parametro tipą).
>> Yra tokia SQL komanda
>>
>> DELETE FROM Detail WHERE MasterUUID = 
>> '8d66bfb5-f638-4e30-ac27-328078122122'
>>
>> šita komanda suveikia per < 1 sekundę, jei leidžiama iš Management 
>> Studio. O jei leidžiama per .Net kodą:
>>
>> SqlCommand cmd = new SqlCommand(string.Format("DELETE FROM Detail WHERE 
>> MasterUUID = '{0}'", masterUUID));
>>
>> ji suveikia per ~20 sekundžių
>> Tačiau jei ji yra va tokia:
>>
>> SqlCommand cmd = new SqlCommand(string.Format("DELETE FROM Detail WHERE 
>> MasterUUID = @MasterUUID");
>> SqlParameter masterUUIDParameter = new SqlParameter("MasterUUID", 
>> masterUUID);
>> cmd.Parameters.Add(masterUUIDParameter);
>>
>> arba parametras pagaminamas taip:
>>
>> SqlParameter masterUUIDParameter = new SqlParameter("MasterUUID", 
>> DBType.Uniqueidentifier);
>> masterUUIDParameter.Value = masterUUID;
>>
>> (konstruktoriuje nurodomas patametro tipas)
>> tada ta pati komanda vykdoma ~2 minutes...
>> Kaip manot, ką .Net'as padaro ir kaip tokių nesąmonių išvengti? Jau ne 
>> pirmą kartą su tokia nesąmone susiduriu. Ypač aktualu, kai trinami dideli 
>> duomenų kiekiai.
>>
>> Indeksas ant MasterUUID kažkiek padeda, bet proporcijos vis tiek išlieka 
>> tos pačios.
>>
>> .Net 2.0