Tema: A: Grieztai siuo klausimu
Autorius: Jornada Del Muerto
Data: 2010-05-18 15:38:52
    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