Entity framework a asociace na DefiningQuery
Skončili prázdniny a jak to momentálně vypadá i pěkné počasí. A tak začíná být více času se věnovat také vývojařině a odpovědím na dotazy.
Sešlo se mi, jak přes kontaktní formulář tak i z konference, hned několik zajímavých otázek, na které přeci jen není takový prostor pro odpověď přímo do diskuze a nebo je škoda je nepublikovat veřejně.
Když to vezmu pěkně popořadě, tedy pozpátku, tak zajímavý dotaz se věnoval Entity frameworku. Zadání bylo celkem jednoduché a šlo o to, že existují dvě entity, které jsou na sebe navázány asociací ve vztahu 1-m. Cílem je vytvoření property, která tento vztah zachová, ale vybere pouze posledních n záznamů. Pavel dokonce poslal i řešení, jak toho docílit přímo v programu, ale toto řešení se mu nepozdávalo
postSet.select(a=> new (a, a.Comment.OrderBy(...).Take(5))
a já se mu příliš nedivím, neboť staví na anonymních třídách a přeci jen je třeba udělat něco navíc než by bylo nutné.
Vytvoření entity a asociace
Mnou navržené řešení spočívá ve vytvoření “nové” entity a definování asociace, nazvěme ji například LastComments, která bude obsahovat pouze posledních n záznamů.
Jak tedy budeme postupovat, abychom se dobrali k finálnímu výsledku. Předpokládejme, že máme databázi, která obsahuje dvě tabulky, jenž jsou na sebe navázány ve správném vztahu.
Založíme si tedy nový projekt a vložíme do něj ADO.NET Entity Data Model. Necháme se provést průvodcem, napojíme se na zdrojovou databázi a přidáme do modelu nám známé dvě entity.
Nový EntitySet s DefiningQuery
Nyní opustíme vizuálního návrháře a vrhneme se do tajů Storage modelu. Ano, je třeba přidat nový entity set, který bude představovat pouze poslední záznamy, které získává EF z databáze. Najdeme si tedy v SSDL schématu [1] EntitySet pro naši entitu komentářů (reprezentující stranu n vztahu) a tuto zkopírujeme,
z takto vytvořeného EntitySetu smažeme atributy store:Type a Schema. Dále EntitySet přejmenujeme na LastComment a do elementu umístíme element DefiningQuery a zde zapíšeme náš dotaz do databáze. Ano, dotaz vypadá obdobně jako ten, který jsem zasílal jako řešení na hádanku Tomáše Herzega.
Soubor ještě nezavírejte, neboť je ještě třeba přidat Entitní typ, který vznikl dotazem do databáze. Najděte si tedy entitu komentářů, zkopírujte ji a změňte ji pouze název.
To by mělo být pro tuto chvíli vše co se týká ruční editace edmx souboru a je možné se vrátit do vizuálního návrháře.
Nová entita a asociace
Nyní už nám schází jen poslední krok a můžeme používat vlastnost LastComments a to je přidání nové entity a asociace. V modelu tedy vytvoříme novou entitu a přidáme do ní potřebné vlastnosti. Na entitě Post si dále zvolíme vytvoření nové asociace, zvolte jméno a obě strany vazby, nezapomeňte vhodně pojmenovat i tzv. Navigation Property.
Nyní si vyberte tuto nově vytvořenou asociaci a v Mapping details okně provedeme mapování jak je naznačeno na obrázku.
Tím je naše mise u konce a nyní můžeme používat tuto vlastnost v projektu.
Nebezpečí číhá všude
Kdybych nyní skončil, asi byste mě po nějaké době používání přestali mít rádi. Proto raději hned upozorním na nebezpečí, které na váš číhá.
První upozornění se týká toho, že dané řešení tak jak je zapsáno je z pohledu vývojáře neměnné. Pokud vývojář začne používat vlastnost LastComments je to správně. Nebezpečí číhá v tom, že jsme náš Storage model upravili a svázali jsme jej tak s konkrétní implementací databázového stroje, v tomto případě MS SQL Serveru 2005 a vyšší. Pokud bychom chtěli migrovat na jiný databázový stroj, je třeba změnit, zdůrazním slovo pouze, SELECT dotaz ve Storage model schématu.
Druhým nebezpečenstvím pak je, že si nejsem jist správností navrženého řešení. Mohu se pouze domnívat, že je to takto správně a doufám, že mě někdo podpoří a navržený postup potvrdí.
Samozřejmě, pokud najdete lepší řešení, které se nebude spoléhat na definici nové entity a asociace, budu rád za jeho zveřejnění.
[1] abychom se přepnuli do možnosti editovat edmx soubor, je třeba kliknout pravým tlačítkem na modelu a zvolit volbu Open with … v dialogu poté zvolit xml editor.