Schizofrenní ORM v podání Microsoftu

Tomáš Herceg       31. 3. 2010       C#, SQL, Offtopic, Databáze       7044 zobrazení

Dnes již si těžko dovedu představit psát aplikaci pracující s databází bez Linq To SQL či bez Entity Frameworku. Přes všechny nevýhody, které mají (moc jich naštěstí není), se s nimi pracuje velmi pohodlně a zvyšují nám produktivitu.

Pokud bychom srovnali jejich funkce, z 90% umí to samé. Jak Linq To SQL, tak i EF mají každý pár funkcí, které ten druhý nemá.

Linq To SQL je mnohými považován za takovou technologii pro začátečníky, hračku, “parodii na ORM” a já nevím, co ještě. To, že podporuje pouze jeden model dědičnosti, a to zrovna ten, který se mi moc nelíbí (Table Per Hierarchy - celá hierarchie tříd je v jedné tabulce a používají se z ní jen některé sloupce). Entity Framework je ve své druhé verzi (označené fikaně jako verze 4, aby to bylo kompatibilní s verzí .NETu) je naproti tomu téměř všemi uznávaný nástroj, který má sice širší možnosti modelování (struktura entit v EF se nemusí krýt přesně se strukturou tabulek v databázi), ale pár věcí, které jsou v Linq To SQL samozřejmostí zase neumí a člověk se jenom ptá “proč sakra”.

Poslední měsíc a půl trávím veškerý svůj volný čas psaním CMS s názvem Uraeus. V databázi se všechno motá kolem tabulky Items, která má jeden sloupeček typu HierarchyID. Každá položka může mít různé atributy, oprávnění (která se dědí) atd., jsou tam různé content-types, každý typ má svou vlastní tabulku, např. Articles, Categories atd., přičemž jsou s položkou provázány vazbou 1:1 přes sloupec ItemId.

Celý obsah CMSka je jeden velký strom a většina dotazů na data je typu “vytáhni mi potomky této položky, vyfiltruj je a nastránkuj je”. Inu napsal jsem si funkci vracející tabulku (fuj to je hrozný překlad “table-valued function”), které předám ID kořenové položky a ona mi vrátí všechny její potomky. Funkce se v SQL totiž používají jako tabulky, dají se filtrovat, řadit, stránkovat atd. Vybrat z funkce můžete třeba SELECT * FROM [dbo].[MojeFunkceVracejiciTabulku](parametr, parametr) atd.

V Linq To SQL je tohle naprosto triviální – přidáte si do datových tříd funkci, zavoláte ji a dostanete IQueryable, nad nímž můžete dělat psí kusy. V okamžiku vyhodnocení na jeden dotaz dostanete vše, co potřebujete.

Když jsem projekt začal psát, použil jsem Entity Framework. V první verzi by mě neudivilo, kdyby neuměl zavolat table-valued function, když neuměl ani volat stored procedury, které vrací cokoliv, ale jenom ty, co vracejí nějakou entitu, pro níž existuje tabulka atd. V jeho druhé verzi jsem to nečekal, když to umí zavolat jakoukoliv stored proceduru, tak to snad bude umět zavolat jakoukoliv funkci. Ale ono ne. 

Nemůžu použít místo table-valud funkce třeba view – ten neumí parametry. Mohl bych použít stored proceduru, ale s těmi je spousta administrativních problémů. Vzhledem k tomu, že používám dědičnost a chci číst entity typu Articles, Categories atd. (je jich asi 10 a budou přibývat), musel bych udělat aspoň jednu proceduru pro každý content-type, což se mi nelíbí. Nastránkovat položky ve stored proceduře jde taky, i když to tu proceduru dost zkomplikuje. Ale dobře, řekněme. Horší je to s filtrováním a řazením – napsat tolik stored procedur pro každé řazení a každé filtrování, které kdy budu potřebovat, není pěkné a co do rozšiřitelnosti to není rozhodně moc elegantní.

Problém stored procedur je totiž to, že vrací hotový výsledek, s nímž už nic neuděláte. Stránkovat a řadit to na klientovi (resp. webserveru) samozřejmě nepřichází v úvahu.

Prozatím jsem si tedy na začátku napsal jednoduchou třídu, které jsem nasypal, co chci a jak to chci vyfiltrovat a seřadit, a ona si vygenerovala SQL dotaz a spustila ho. Bohužel se ukázalo, že když potřebuji dělat nějaké agregace či joiny s dalšími entitami, tak to sice jde, ale opět se mi to přestalo líbit. Udělal jsem tedy v Subversion branch, smazal Entity Data Model a přidal Linq To Sql Classes.

Linq To SQL neumí dědičnost Table per Class, kterou používám – třídy Article, Category atd. dědí z Item, každá má svou tabulku. Vzhledem k tomu, že mám poměrně pěkně napsanou datovou vrstvu v projektu, moc to nevadilo – udělal jsem rozhraní, které všechny třídy spojuje, a bylo hotovo.

Jak typické - speciálně mně se musí zrovna stát, že potřebuju takovou sadu funkcí, kterou mi ani jeden ORM nenabídne. To je také důvod, proč jsem se včera večer naštval a dnes odpoledne jsem v jednom dost rozsáhlém projektu přemigroval z Entity Frameworku na Linq To SQL. Naštěstí to nedalo tolik práce, ale jestli mi ještě někdo řekne, že je Linq To Sql hračka a EF pořádný nástroj, asi mu odpovím “jak kdy!”. Pro můj konkrétní projekt je Linq To SQL menší zlo.

Nechápu ale, proč Microsoft vyvíjí dvě technologie – kdyby Linq To SQL zavrhnul a všechno, co umí navíc (ale tady opravdu zdůrazňuji všechno!!!) přidal i do Entity Frameworku, mohl by mít skvělý a funkcemi nabitý ORM místo dvou podobných, z nichž každý umí něco extra, ale žádný neumí všechno, co člověk může potřebovat najednou. Anebo ať Entity Framework naučí datový typ HierarchyId, když už si ho vymysleli.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Diskuse: Schizofrenní ORM v podání Microsoftu

Linq To SQL a Entity Framework jsou 2 různé abstrakce nad práci s daty. Linq to SQL je uzce vázán na MSSQL a z toho důvodu v něm jsou dělat daleko více speciality tohoto databázového stroje. Bohužel L2SQL není vázán na verzi MSSQL, tak na nové cool datové typy MSSQL2008 můžeme zapomenout (proto absence HIERARCHYID).

Oproti tomu EF je databázově neomezený a proto jsou u něj jen standartní datové typy použitelné ve všech databázích. Dále už nemůže spoléhat na to, že funkci můžeme použít jako zdroj selectu. EF je o jednu abstrakční úroveň výše díky mapování tabulek.

Každý framework se hodí na něco jiného. Pokud potřebuji vyšší abstrakci a šírší databázovou použitelnost (MSSQL, ORACEL,...), zvolím EF. Pokud potřebuju vyšší vazbu na DB (třeba tebou popsaný příklad) použiji L2SQL za cenu nižší abstrakce (vazba tabulek na model 1:1 - to je i důvod jen k jedné variantě dědičnosti)

Oba frameworky mají velikou sílu a jde jen o to jak se k tomu člověk chce postavit. L2SQL není jen hračka, to tvrdím ačkoli ho nepoužívám.

Jinak je tu staré dobré ADO.NET a jsem zastáncem toho, než abych to někde složite rouboval, radši si speciality dotahnu ručně (třeba MERGE)

(a ješte k VB.NET: nejde se přihlásit přes LiveID)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Schizofrenní ORM v podání Microsoftu

... tohle mi mluví úplně z duše. Protože jsem databázově myslící tvor, prostě navrhnu databázi a pak na tom spustím sqlmetal a je vymalováno.

Na LinQ to SQL mě ovšem neskutečně štvou některé věci, jako jsou například výchozí hodnoty po inicializaci (http://blog.vyvojar.cz/xzajic/archive/20... ) nebo zhovadilý způsob mazání (http://blog.vyvojar.cz/xzajic/archive/20... ). Pokud se tomu ale přijde na kloub, dá se s tím přežít.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback