Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc

V první řadě bych se chtěl omluvit Otovi Pavlovi, za parafrázi na název jeho úžasné prózy. V druhé řadě pak čtenářům, že do technického blogu vkládám svoje politologické úvahy. Nikomu nic nevnucuji, ale za svoje názory se nestydím Smile

Před týdnem jsem se vrátil z dovolené u moře, konkrétně z Kréty. Za ty dva roky, co jsem v Řecku nebyl se jedna podstatná  věc změnila - Rusové jsou na každém kroku, a není to pro mne nic příjemného. Za svých 18 let v totalitě mám na trochu rusofobie nárok. Je to jednoduché - s růstem cen ropy roste národní důchod, s národním důchodem roste moc, s mocí roste sebevědomí. Zachází to do takových absurdit, že v některých místech je z 10 obchodů zhruba 5 s kožichy (v červenci na Krétě!!!)

To mne přimělo k úvaze, kam vlastně Evropa kráčí. Svět nebude asi nikdy idylickým místem. Lidé tvoří státy a státy prosazují svoje zájmy. Jak jde čas, mění se ospravedlnitelné prostředky k méně násilným - naštěstí (doporučená literatura - Henry Kissinger, Dějiny diplomacie). Reálnými velmocemi se stále více stávají Německo a Rusko, nikdo jiný v Evropě není na obzoru. Evropská unie se neshodne na ničem a Francie se utápí v iluzích o své vyjímečnosti, zatímco její význam upadá. Naše pozice mezi Ruskem a Německem není zrovna záviděníhodná - Polsko by mohlo vyprávět.

A proto říkám na rovinu - chci tady ten radar. Už jenom to, že Rusové radar nechtějí, je dostatečný důvod, proč ho tady chtít. Nedělám si iluze o Americe a jejích motivech. Je to ale pořád nejlepší kůň, na kterého lze vsadit. Američané přišli dvakrát Evropě na pomoc, zatímco Rusové nás dvakrát obsadili (pravda, poprvé přitom vyhnali jiné okupanty). Srovnání radaru s rokem 1968 je opravdu urážkou svědčící o naprosté ignoranci toho, kdo to tvrdí. O to více mne znechucuje, jak strana, která s jednáním začala později zjistí, že z hlediska průzkumů veřejného mínění je lepší radar nemít. Jejich "expert" Zaorálek by klidně mohl být velvyslancem Ruska v ČR. Kvůli pár procentům ve volbách lze vsadit i bezpečnost země. Aspoň vím, koho nebudu volit. Doufám, že vy taky ne...

Během prázdnin jsem našel čas na mírný krok stranou od svých obvyklých činností. Připravil jsme dva webcasty, během kterých jsem si vyzkoušel produkty, které normálně nepoužívám. Přináším pár postřehů a - nutně subjektivních - dojmů.

V prvním se věnuji přístupu k TFS z jiných prostředí. Zde byl zajímavý zejména Eclipse. Uživatelské prostředí má některé výborné nápady (např. strom souborů s rozpadem až na metody objektů, s vizualizací chyb a varování). Instalace (v podstatě kopírování) je také příjemné, jenom jsem v kombinaci s JDK, Ant a Teamprise pluginem chvíli bojoval se správným nastavením cest a proměnných, přece jenom to není věc na MS platformě úplně typická. Jiné věci mi připadly nesmyslně těžkopádné - Eclipse je sice výborně rozšiřitelný, ale jednotlivé doplňky jsou (oproti VS) dost slabě provázané. Určitě bych za VS neměnil, ale celkové hodnocení by bylo velmi dobré.

Ve druhém webcastu migruji data z jiných produktů do TFS.

  • Prvním byl SourceSafe - nostalgické vzpomínání na doby, které jsou naštěstí za námi. Ve srovnání s TFS působí jako z pravěku. Obzvláště nepoužitelný mi přijde koncept paralelního vývoje Share/Pin namísto Branch/Merge. Přesto se právě funkčnosti Share mnozí dnešní uživatelé dožadují (ne, není tam a ani se nechystá).
  • Dalším nástrojem byl Subversion, což je oproti SourceSafe výrazně jiný kalibr. Líbí se mi na něm zejména integrace do Windows Exploreru, což TFS nemá (snad by měl být někdy koncem roku Power Tool). Zajímavá je i možnost provést checkout (neříká se tomu tak :-) bez nutnosti serveru díky větší "tloušťce" klienta. Právě větší tloušťka klienta má svoje pro a proti - v TFS je vše více centralizováno na serveru, což umožňuje dobrou rozšiřitelnost serveru, jemnější nastavení práv na jednotlivé operace, větší kontrolu apod. avšak za cenu horší funkce offline (chybí lokální historie). TFS exceluje hlavně integrací s pracovními položkami a s buildem, což je v Subversion těžká úloha, jejíž výsledek je vždy horší než u TFS. Pro prosperující firmu by se zakoupení licence v řádu stovek dolarů na uživatele mělo stát dobře návratnou investicí (navíc partneři MS mají řadu licencí zadarmo). Subversion je dobrou alternativou pro někoho, kdo se spokojí s horším, leč stále slušným celkovým výsledkem výměnou za úsporu za licence.
  • Nakonec jsem si vyzkoušel programovou migraci dat na TFS (v mém případě ze SharePointu, ale to není důležité) - vzhledem k tomu, jak málo kódu píšu, jsem sám sebe zaskočil tím, že jsem kód pro uložení na TFS napsal napoprvé správně. Není lepší důkaz snadnosti objektového modelu :-)

Oba webcasty lze stáhnout zde http://www.microsoft.com/cze/msdn/webcasts/default.mspx

Nevím, zda mi něco uniklo. Nová CTP SQL 2008 jsem sledoval velmi podrobně, ale o této novince jsem se nikde nedočetl. O to větší bylo moje překvapení, když jsem ji objevil. O co jde? V SQL Management Studiu najdete na toolbaru nenápadné nové tlačítko:

image

Slouží k ladění T-SQL skriptů zapsaných v okně editoru. Konkrétně to může vypadat např. takto.

image

Fungují i pokročilejší věci, jako např. nastavování breakpointu, Step Into (např. do uložené procedury nebo funkce) apod.

P.S. Nevím, zda to funguje i proti starším verzím SQL serveru.

V předchozím článku jsem se zabýval sdílením videonahrávek na Internetu, dnes se podíváme na přenos živého videa. Zajímá mě scénář jednorázového přenosu, nesnažím se o scénáře typu hlídání domu videokamerou - pro tyto situace jsou mnohem robustnější jednoúčelová hardwarová zařízení, případně i software.

Pro přenos potřebujete v zásadě dvě komponenty.

První krok - převod videozáznamu do streamu

Zde Microsoft nabízí hned dva produkty. Prvním je Windows Media Encoder 9 Series (obrázek níže). Je zdarma, ale není už nejnovější - publikován 1.7.2003. Přesto poslouží dobře, kodeky jsou na solidní úrovni. Pokud ho chcete provozovat na Windows Vista, nezapomeňte nainstalovat fix na kompatibilitu. Více informací najdete např. na Wikipedii.

clip_image002

Jeho nejnovějším nástupcem je Expression Encoder 2 (Trial ke stažení, obrázek níže), plná verze stojí 199 USD a umí samozřejmě mnohem víc věcí (konverze formátů a různé další finty).

clip_image002[4]

Jak je vidět, uživatelské rozhaní za ty roky poněkud poskočilo, ale jinak oba nástroje fungují v zásadě stejně. Obraz a zvuk z nějakého zařízení převádějí na stream. Ten je buď tlačen (push) na Windows Media Server pomocí HTTP protokolu, anebo je vysílán za využití multicast paketů po lokální síti. Připojených klientů může být maximálně deset a očekávejte problémy, pokud jsou uživatelé na jiné lokální síti (nemluvě o tom, když jsou za firewallem). Multicast je sice teoreticky možný i po internetu, ale prakticky je to téměř vyloučeno.

Druhý krok - distribuce streamu uživatelům

Na Internetu může být více uživatelů než 10. Také se typicky používá unicast, tj. server posílá každému klientovi "jeho" stream. Což jsou dva důvody, proč vám nestačí Encoder a potřebujete Windows Media Services, které jsou schopné unicast stream vysílat velkému množství klientů.

Buď můžete použít metodu pull, kdy si Windows Media Services přebírají od Encoderu stream - připojují se k němu stejně jako "obyčejní" klienti a obdržená data posílají dál (na serveru zadáte http://adresa_klienta:port_encoderu). Druhou možností je použít push připojení - na serveru zadáte push:* a v Encoderu musíte zadat http://jmeno_wms_serveru/jmeno_publishing_pointu. Z hlediska koncového diváka je to úplně jedno. Push uspořádání má drobnou výhodu v tom, že na WMS nemusíte záznam pouštět - Encoder si server řídí vlastně sám. Pull má zase tu výhodu, že s jeho pomocí snadno vytvoříte farmu serverů. Volba bude ale spíše záviset na tom, kde je jaký firewall a kterým směrem lze přes něj posílat data. Přenos ve WMS pak vypadá následovně (nuda, co?):

image

Nemyslím teď YouTube, Silverlight Streaming a podobně - myslím sdílení videosouborů na vlastním webovém serveru. To lze udělat různými způsoby, které se často pletou, proto bych je chtěl trochu vyjasnit.

Úroveň 1: Nejjednodušší přístup

Nejjednodušší přístup je opravdu jednoduchý. Vezmu soubor a nakopíruji ho do virtuálního adresáře na web serveru, stejně jako bych to udělal s obrázkem. Přehrávačem pak může být Windows Media Player anebo soubor mohu různými způsoby vložit do webové stránky (např. vytvořit přehrávač v Silverlight a předat mu odkaz na videosoubor). Většina přehrávačů je natolik chytrá, že přehrávání spustí, jakmile si ze serveru stáhne "právě dost" obsahu, zbytek souboru se pak stahuje na pozadí - a to maximální možnou rychlostí, kterou server, klient a síťové spojení mezi nimi dovolí (tzv. progressive download). Zátěž sítě je vidět na obrázku:

image

Úroveň 2: Optimalizace síťové komunikace

Kopírování "stejně jako obrázek" v předchozím případě má jeden zádrhel: video totiž není obrázek. Zatímco obrázek chci jistě na stránce vidět celý, drtivá většina uživatelů video nedokouká do konce. Pokud mu ho pošleme celé co největší rychlostí, promrhali jsme zbytečně spoustu kapacity síťové linky, které se nám může záhy nedostávat - při připojení více uživatelů a velikosti videa je to celkem rychle nastávající scénář.

Abychom tomu zabránili, lze na IIS 7 použít modul, což je bezplatný doplněk IIS 7 - je k dispozici pro x86 i x64 platformu. Tento doplněk si přečte z metadat příslušného multimediálního souboru potřebnou šířku pásma (v mém případě 120 kbps) a při odesílání na klienta "brzdí" přenos na rychlost odpovídající danému médiu plus rezerva na nastavený počet sekund dopředu - viz obrázek.

image

Efekt na síťovou komunikaci je patrný - objem přenášených dat za jednotku času je výrazně nižší (viz obrázek níže). Jednotlivé peaky jsou způsobeny mým pohybem v čase přehrávaného videa (operace Seek), pak se samozřejmě musí příslušný počet sekund dopředu znovu natáhnout a objem přenášených dat tak krátkodobě vzroste.

image 

Úroveň 3: Nejdokonalejší

Nejdokonalejší, ale zároveň složitější způsob na nastavení přinášejí Windows Media Services. Fungují jako nová role pro Windows Server 2008, která se nainstaluje odtud. K dispozici jsou ale i pro předchozí verze serverových operačních systémů.

image

Administrace se pak provádí jiným nástrojem (obrázek níže), neboť s IIS nemají Windows Media Services nic společného. Nepoužívá HTTP protokol, ale místo toho protokoly RTSP (specifikace RFC 2326) a RTP (specifikace RFC 3550). To se také projevuje tím, že adresa videa začíná mms:// a ne http:// jako v předchozích případech.

image 

Když se podíváme na záznam síťové komunikace je ještě lepší než předtím - hlavně peaky jsou nižší.

image

Je to dáno primárně tím, že server "rozumí" tomu, co posílá. Takže např. při posunu (Seek) ví přesně, co poslat. Rozumí šířce pásma, latenci a dalším věcem.

A má celou řadu dalších výhod - umožňuje multicast přechod, zabraňuje zcizení (stažení) videa klientem, a řada dalších - nebudu opakovat co napsali jiní, třeba tady.

Před rokem a něco jsem si napsal vlastní ovládací prvek k editaci pole na formuláři Work Itemu ve Visual Studiu (více zde). Jednalo se o WinForms prvek implementující speciální rozhraní pro práci s položkou WorkItem, který může sloužit k modifikaci zobrazování, vkládání, validace pole apod. Vmém případě zajišťuje, aby se pole Completed Work mohlo pouze zvyšovat, nikdy snižovat.

Mezitím byl vydaný VSTS Web Access Power Tool, což je webový přístup k datům v TFS, včetně pracovních položek Work Items. Výše uvedený prvek zde nejde použít (ASP.NET a WinForms jsou od sebe přece jenom poněkud daleko). Naštěstí poslední edice umožňuje vlastní webové ovládací prvky pro položky Work Items, po instalaci najdete v podadresáři SDK dokumentaci ve Wordu a pár příkladů.

Víceméně ze cvičných důvodů jsem se do tohoto úkolu pustil, ale to jsem ještě netušil, co mne čeká. Celá aplikace je prolezlá AJAXem, na serveru se udržuje ASP.NET formulář pro editační seanci trvale v paměti s pravidelným úklidem. Stavový HTML formulář v prohlížeči na klientovi a stavový ASP.NET formulář na serveru si spolu neustále povídají pomocí AJAX volání - brrrrrrr. Ať mi někdo chvíli vykládá, že v AJAXu je budoucnost aplikačního vývoje. AJAX na prominentní aplikace typu webových map je fajn, ale cena za něj zaplacená v podobě složitosti vývoje je děsivá.

Výsledný kód je nakonec relativně jednoduchý, ale než jsem pochopil jak vše funguje a zorientoval se v rozmazané hranici mezi klientem a serverem... uplynulo hodně hodin. V příloze najdete kód pro WinForms i ASP.NET variantu ovládacího prvku.

Brian Harry na svém blogu uveřejnil informace o nové edici Power Tools pro TFS, která je ke stažení zde. Z novinek mne zaujaly dvě.

První je výrazné vylepšení použitelnosti Work Item Templates, které nyní mají intuitivní uživatelského rozhraní. Krátké vysvětelní pro ty, kdo WIT šablony neznají - slouží typicky buď k vytvoření nového work itemu s již předvyplněnými vybranými poli (pokud jich zakládám více podobných) anebo k hromadné editaci více workitemů vybraných ve výsledku dotazu pomocí Ctrl-Click (např. přesun více úloh do jiné iterace).

Druhou je TFSServerMonitor, kterým nahlédnete dovnitř serveru. Zatímco Best Practices Analyzer (součást PT už zhruba půl roku) kontroluje správnost nastavení TFS, TfsServerMonitor vám přes dostupná API zobrazí charakteristiky serveru, velikost dat, aktivitu na serveru podle typu dotazu, uživatele, aplikace apod. Screenshoty jsou zde, i když zobrazená verze se od té v PT mírně liší.

Užitečné nástroje pro každého, kdo má TFS...

 

Pokud se rádi díváte do zákulisí, Jeff Beehler upozorňuje ve svém blogu na 4 příspěvky na "Team WIT Tools", kde se popisuje využití TFS při vývoji Visual Studia. Je to velmi zajímavé včetně screenshotů formulářů a popisu uspořádání zdrojového kódu a tzv. Quality Gates.

Aha, ještě link - http://blogs.msdn.com/jeffbe/archive/2008/04/20/how-devdiv-uses-tfs.aspx

 

V předchozích třech dílech jsem se věnoval víceméně technickému popisu, dnes se pustím na horkou půdu subjektivních hodnocení. Nejsem první, kdo se na toto téma zamýšlí, asi nejznámnější srovnání je zde. "Oficiální" Microsoft srovnání pokud vím zatím není. Každopádně se tyto dvě technologie do značné míry překrývají.

Nejzásadnější rozdílná věc je počet mapovacích vrstev. Zatímco LINQ to SQL je víceméně typový wrapper nad databází vytvořený 1:1 oproti databázové struktuře, ADO.NET Entities (Entity Framework, EF) pracují s konceptuálním modelem zcela nezávislým na databázi, který se mapuje na tzv. storage model (který je 1:1 popisem databáze nebo její podmnožiny). Z tohoto koncepčního rozdílu vychází většina skutečných rozdílů mezi technologiemi. Proto je někdy LINQ to SQL představován jako technologie pro rychlý vývoj (RAD) vytvořením silně typové vrstvy nad databází, zatímco EF jsou představovány jako technologie pro vytváření dlouhodobě udržitelných aplikací (díky izolaci kódu od změn v databázi). Toto dělení je podle mne dosti umělé - pokud totiž zůstanu u základní funkčnosti ADO.NET Entities, může být vývoj stejně rychlý a stejně RAD jako u LINQ to SQL, takže zde žádnou výhodu pro LINQ to SQL nepozoruji.

Co umí LINQ to ADO.NET Entities navíc:

  • Výrazně bohatší možnosti modelování - navíc podpora komplexních typů, mapování entity do více tabulek, více entity setů pro jednu entitu, dědičnost typu table per type (TPT), relace M:N bez nutnosti pomocné entity (více viz 3. část - Možnosti modelování)
  • Nezávislost na databázi - EF je postavený na principu poskytovatelů pro daný typ databáze, zatímco LINQ to SQL je pevně svázán s MS SQL 2000+

Co umí LINQ to SQL navíc:

  • Větší variabilta pro řešení konfliktů při ukládání - pro každé pole je možné kontrolu zapnout/vypnout/zapnout-jenom-při-změně. V EF poslední možnost chybí.
  • O něco komfortnější vygenerovaný objektový model - např. OnValidate(), RemoveAll(), GetChangeSet() - vše jde ale snadno dopsat i do EF a možná se to ve finální verzi též objeví.
  • Jsou k dispozici již teď - EF budou dokončeny až během léta
  • LINQ to SQL umožňuje nastavit Delay Loading (tj. automatické dodatečné natažení) pro individuální pole (např. velký BLOB v tabulce). Řešení v EF je oddělit BLOB do separátní tabulky (což je ovšem z databázového hlediska doporučené řešení) a namapovat entitu asociací 1:1.

Odlišnosti (ve skutečnosti jenom jedna, o které vím):

  • LINQ to SQL je daleko horlivější v automatickém natahování dat z databáze - nemusíte se opravdu o nic starat. EF je mnohem konzervativnější - natáhne se jenom to, na co se explicitně zeptáte. Pokud chcete přejít na asociaci, musíte explictně zavolat Load() anebo při výběru entit z úložiště použít Include(jmenoAsociace) pro automatické (a velmi efektivní) natažení. Nechci hodnotit co je lepší.

Abych to shrnul - když si vše sečtu, jednoznačně mi vychází EF jako bezpečná volba prakticky ve všech situacích. Pár výhod LINQ to SQL lze snadno obejít, zatímco výhody EF pro dobrou architekturu a udržitelnost aplikace jsou evidentní. Vývoj s EF navíc může být prakticky stejně snadný jako s LINQ to SQL. Dle mého subjektivního názoru se tedy LINQ to SQL jeví jako téměř mrtvě narozené dítě...

Dále vyšlo:

Ve třetí části miniseriálu se podíváme, co všechno lze v Entity Frameworku namodelovat. Pozor, ne všechno, co lze nastavit v modelovacích souborech, je též podporováno ve vizuálním designeru - alespoň ve verzi Beta 3. Některé věci snad budou podporovány ve finální verzi designeru, těžko teď odhadnout. Seznam níže je výčtem možností, na které jsem v různých článcích narazil a prakticky je vyzkoušel. Příklady i příslušná databáze jsou v příloze.

V rámci jedné entity lze namodelovat následující:

  • Komplexní (strukturované vlastnosti) - lze nadefinovat napr. typ Adresa (Ulice, Mesto, PSC) a pak lze pouzivat konstrukce typu karel.AdresaDomu.PSC, karel.AdresaPrace.Ulice - všechna data jsou přitom v jedné tabulce. Není podporováno v Beta 3 verzi designeru.
  • Entitu lze mapovat na více tabulek - v databázích bývá běžné, že se z výkonnostních důvodů velká pole, BLOBy apod. vyjmou do extra tabulky. Přitom je možné mít jednu entitu a kód "neví" o tomto rozdělení.
  • Více Entity Setů pro jednu entitu - lze například mít definovanou entitu Firma, která se nachází ve dvou tabulkách - Dodavatele a Odberatele. Těmto dvěma tabulkám pak odpovídají dva entity sety, přičemž entita je stejného typu. Není podporováno v Beta 3 verzi designeru.
  • Aktualizace dat pomocí uložených procedur - namísto auto-generovaných SELECT/INSERT/UPDATE/DELETE lze používat uložené procedury. Není podporováno v Beta 3 verzi designeru (oprava, jde to).
  • Volání uložených procedur pomocí typových wrapperů (function import) - mohou vracet buď skalární údaje anebo entity

Je též možné vytvářet dědičnost mezi entitami. Jsou podporována dvě schémata uložení dat:

  • Table per hierarchy (TPH) - všechny třídy mající společného předka jsou v jedné tabulce se sloupečky pro všechny vlastnosti všech typů. Jeden sloupeček určuje konkrétní typ. Je to jednoduché a rychlé, ale vede to k dosti řídkým tabulkám a komplikuje validaci správnosti dat na databázové vrstvě.
  • Table per type (TPT) - každý typ má svoji tabulku, která se liší sloupci navíc od typu, ze kterého se dědí (tabulka obsahuje kompletní údaje typu). Jednoduché, rychlé, ale nepříliš efektivní pro dotazy vracející více konkrétních typů.
  • Table per sub-class (TPC) - zřejmě není podporováno. V jednom článku jsem našel opačné tvrzení, ale nic dalšího ho nepodporuje. Z databázového hlediska nejčistší, i když dost komplikovaný způsob. Každý typ má svoji tabulku obsahující nové vlastnosti a 1:1 relaci na tabulku bázové třídy. Může vést k dotazům s velkým množstvím JOIN vztahů. Každopádně to zřejmě nejde namapovat, takže další diskuse je zbytečná.

Mezi entitami je samozřejmě možné mít asociace pomocí navigačních vlastností, a to všech běžných typů:

  • 1:N - nejčastější situace - objednavka.Polozky, kategorieKola.Produkty
  • 1:1 - méně běžné - karel.CV, tohleCV.Osoba
  • Parent:child - speciální případ 1:N, kdy relace je v rámci jedné entity - karel.Manazer, karel.Podrizeni
  • M:N - v databázi se to řeší dvěma relacemi typu 1:N a pomocnou tabulkou - např. Osoby, Jazyky a pomocná OsobyJazyky. V EF je samozřejmě možné modelovat jako dvě relace s pomocnou entitou. Pokud ale pomocnou tabulku uděláte tak, že obsahuje pouze klíče z dalších dvou tabulek a primární klíč je přes všechny sloupce, lze to udělat i bez "mezientity" a pak používat elegantní a primocarou konstrukci - karel.Jazyky a nemcina.Osoby.

Další čtení - http://www.code-magazine.com/article.aspx?quickid=0712022 a http://www.code-magazine.com/article.aspx?quickid=0712032

Dále vyšlo:

Ve svém prvním příspěvku jsem to schytal za slovo "revoluční". Řekl bych, že trochu neprávem. Netvrdím, že jsou Entities něčím revolučním v globálním pohledu, ale něčím revolučním na datové platformě Microsoft (což je ADO, resp. ADO.NET). Spíše bych řekl, že Microsoft uplatnil svůj typický přístup - počkat si, jak se věci vyvinou, poučit se a pak to vzít za trochu jiný konec, čímž vznikne něco snadno použitelného, co obsáhne mnohem širší publikum (což Hibernate při vší úctě není, pro ne-profi vývojáře je to "trochu moc", čímž rozhodně nechci říct, že je sám o sobě špatný).

Zpět k objektovému modelu. Při práci s Entities je možné použít tři různé úrovně:

  1. Connection/Command/DataReader - tradiční přístup z relačního světa je možné uplatnit i proti virtuální databázi entit. Bohužel není tímto způsobem možné data modifikovat, pouze číst. Také to není vůbec komfortní, protože musíte psát Entity SQL příkazy ručně a výsledky dostanete netypově - musíte si přetypovat do svých typů. Asi to bude spíše využíváno v různých reportovacích a dalších nástrojích, které s daty pracují (a fungují s ADO.NET providery), než ve vašdm kódu
  2. eSQL dotazy proti kontextu entit s pomocí CreateQuery<T> - tímto způsobem se vám vrátí typový výsledek, se kterým můžete dál pracovat - modifikovat data, mazat je, přidávat přes kontext nová data atd. Dotaz je opět pomocí Entity SQL, tudíž ne moc komfortní. To ale může být někdy výhoda, např. když chceme dotaz dynamicky skládat z předem neznámého počtu fragmentů (filtrů, třídění apod.) - objektový model je na tento typ skládání uzpůsoben.
  3. LINQ dotazy proti kontextu, který zpřístupňuje jednotlivé entity sety jako typové kolekce - zdaleka nejkomfortnější práce s plnou podporou kontroly syntaxe při kompilaci, IntelliSense atd. Modifikace dat je stejná jako v předchozím případě. Tento způsob bude ve většině scénářů asi nejčastější.

Co všechno entities umí:

  • Prakticky kompletní podpora LINQ konstrukcí - Select, Where, OrderBy, GroupBy, Join, ...
  • Modifikace dat (vkládání, mazání, editace)
  • Pozdní vyhodnocení dotazu - tak aby se minimalizovalo množství dat získávaných z databáze
  • Object Identity - každá entita se v rámci kontextu natáhne pouze jednou (nemohou být dva objekty pro tutéž entitu)
  • Předkompilaci dotazů pro rychlejší provádění
  • Detekce konfliktů (optimistický přístup) - u sloupečků s nastaveným ConcurrencyMode.Fixed se při ukládání kontroluje, zda mi je někdo "pod rukama" nezměnil
  • Transakce - běžným způsobem v .NET Frameworku - uzavření kódu do bloku using(TransactionScope)
  • Kontrola načítání entit - při navigaci mezi entitami se entity natahují pouze na vyžádání. Chcete-li je "před-natáhnout" abyste minimalizovali počet dotazů do databáze, použijete Include() v dotazu (tzv. eager fetching)

Kód který všechny tyto možnosti ilustruje jsem nakopíroval na konec tohoto článku (využívá databázi AdventureWorksLT). Celé řešení pro Visual Studio 2008 + Entities Beta 3 je navíc v příloze.

Další čtení - http://www.code-magazine.com/article.aspx?quickid=0712042

Dále vyšlo:

P.S. Tohle je druhý příspěvek napsaný pomocí Live Writer. Jak jsem bez něj mohl dříve žít?

 

            // K entitam lze pristupovat pomoci poskytovatelu a jazyka eSQL (jako k beznym relacnim datum) ??? 

            using (EntityConnection conn = new EntityConnection(ConfigurationManager.ConnectionStrings["AdventureWorksLTEntities"].ConnectionString))

            {

                EntityCommand cmd = new EntityCommand("SELECT p.Name,p.ListPrice FROM AdventureWorksLTEntities.Products AS p WHERE p.ProductCategory.Name='Socks' AND p.ListPrice>@Cena ORDER BY p.ListPrice DESC", conn);

                cmd.Parameters.AddWithValue("Cena", 9);

                conn.Open();

                EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);

                while (rdr.Read())

                {

                    Console.WriteLine("{0} ({1})", rdr["Name"].ToString(),rdr["ListPrice"].ToString());

                }

                conn.Close();

            }

            // Lepsi je ale ve vetsine pripadu pouzivat objektove sluzby

            using (AdventureWorksLTEntities aw = new AdventureWorksLTEntities())

            {

                // Jednou moznosti je delat standardni eSQL dotazy

                var dotazProdukty = aw.CreateQuery<Product>("SELECT VALUE p FROM Products AS p WHERE p.ProductCategory.Name='Socks' AND p.ListPrice>@Cena ORDER BY p.ListPrice DESC");

                dotazProdukty.Parameters.Add(new ObjectParameter("Cena",9));

                foreach(var p in dotazProdukty)

                    Console.WriteLine("{0} ({1})",p.Name,p.ListPrice);

                // Druhou moznosti je pouzit postupny builder pro dotazy - umoznuje dynamicke skladani

                var dotazProdukty2 = aw.CreateQuery<Product>("Products");

                dotazProdukty2 = dotazProdukty2.Where("it.ListPrice>@Cena",new ObjectParameter("Cena",9));

                dotazProdukty2 = dotazProdukty2.Where("it.ProductCategory.Name='Socks'");

                dotazProdukty2 = dotazProdukty2.OrderBy("it.ListPrice DESC");

                foreach (var p in dotazProdukty2)

                    Console.WriteLine("{0} ({1})", p.Name, p.ListPrice);

                // Treti, casto nejpohodlnejsi je delat standardni LINQ dotazy a vyuzivat relace mezi daty

                // Stejne jako v LINQ - bud pomoci klicovych slov anebo extenznich funkci

                var produkty1 = from p in aw.Products where p.DiscontinuedDate == null orderby p.ListPrice select p.Name;

                var produkty2 = aw.Products.Where(p => p.DiscontinuedDate == null).OrderBy(p => p.ListPrice).Select(p => p.Name);

                //// Mozno vytvaret hierarchie anebo ploche struktury

                var plocha1 = from p in aw.Products where p.ProductCategory.Name.Contains("Bikes") select new { p.Name, Category = p.ProductCategory.Name };

                var plocha2 = aw.Products.Where(p => p.ProductCategory.Name.Contains("Bikes")).Select(p => new { p.Name, Category = p.ProductCategory.Name });

                var hierarchie1 = from c in aw.ProductCategories where c.Name.Contains("Bikes") select new { c.Name, c.Products };

                var hierarchie2 = aw.ProductCategories.Where(c => c.Name.Contains("Bikes")).Select(c => new { c.Name, c.Products });

                //// Pokud je realace v databazi, je vyhodne ji primo vyuzit, jinak je mozne pouzit join (dost umely priklad :-)

                var dvojiceAdres = from a1 in aw.Addresses join a2 in aw.Addresses on a1.City equals a2.City select new { a1, a2 };

                // Samozrejme je mozne manipulovat s daty

                // Pridani entity

                Product hrnek = new Product() { Name = "Bily hrnecek", ProductNumber = "HR-BI-007", SellStartDate = DateTime.Now, SellEndDate = DateTime.Now.AddYears(1), ModifiedDate = DateTime.Now };

                aw.AddToProducts(hrnek);

                aw.SaveChanges();

                // Editace entity a zaroven presun v ramci referencni integrity

                Product hrnek2 = aw.Products.First(p => p.ProductNumber == "HR-BI-007");

                ProductCategory prislusenstvi = aw.ProductCategories.First(c => c.Name == "Accessories");

                hrnek2.SellEndDate += TimeSpan.FromDays(60);

                hrnek2.ProductCategory = prislusenstvi;

                aw.SaveChanges();

                // Vymazani entity z databaze

                Product hrnek3 = aw.Products.First(p => p.ProductNumber == "HR-BI-007");

                aw.DeleteObject(hrnek3);

                aw.SaveChanges();

                // Deffered Execution - vyhodnoceni se odklada az na posledni mozny okamzik, aby se minimalizovalo mnozstvi nactenych dat

                var kola = from p in aw.Products where p.ProductCategory.Name.Contains("Bikes") select p;

                var drahaKola = from p in kola where (p.ListPrice > 3000) && (p.DiscontinuedDate == null) orderby p.Name select new { p.Name, p.ListPrice };

                var seznamDrahychKol = drahaKola.ToList(); //az ted se pusti dotaz

                // Object Identity - sleduje se identita objektu, jedna entita v databazi = jeden objekt v pameti

                var kategorie1 = aw.ProductCategories.First(c => c.Name == "Accessories");

                var kategorie2 = aw.ProductCategories.First(c => c.Name == "Accessories");

                bool jsouStejne = object.ReferenceEquals(kategorie1, kategorie2);

                // Compiled query - pokud se vyuziva opakovane, setri to cas na vyhodnoceni

                Func<AdventureWorksLTEntities, string, IQueryable<Product>> productsByCategory =

                    CompiledQuery.Compile((AdventureWorksLTEntities db, string categoryName) =>

                        from p in db.Products where p.ProductCategory.Name.Contains(categoryName) select p);

                var p1 = productsByCategory(aw, "Shorts");

                var p2 = productsByCategory(aw, "Bikes");

                // Optimistic concurrency

                // Konflikt se detekuje na zaklade vlastnosti ConcurrencyMode.Fixed u vlastnosti Name, u ostatnich neni kontrola!

                try

                {

                    ProductCategory c = new ProductCategory() { Name = "Pokus", ModifiedDate = DateTime.Now };

                    aw.AddToProductCategories(c);

                    aw.SaveChanges();

                    // Simulace vyvolani zmen mimo tento datovy kontext

                    using (AdventureWorksLTEntities aw2 = new AdventureWorksLTEntities())

                    {

                        var pokus = aw2.ProductCategories.First(p => p.Name == "Pokus");

                        pokus.Name="Pokus2";

                        pokus.ModifiedDate=DateTime.Now;

                        aw2.SaveChanges();

                    }

                    // Tato editace skonci konfliktem

                    c.Name = "Pokus3";

                    aw.SaveChanges();

                }

                catch (OptimisticConcurrencyException ex)

                {

                    foreach (var se in ex.StateEntries)

                    {

                        Console.WriteLine("ID ={0}", ((ProductCategory)se.Entity).ProductCategoryID);

                        Console.WriteLine("BEFORE REFRESH");

                        for (int i = 0; i < se.CurrentValues.FieldCount;i++ )

                            Console.WriteLine("   {0} - current:{1}, original:{2}", se.CurrentValues.GetName(i), se.CurrentValuesIdea.ToString(), se.OriginalValuesIdea.ToString());

                        aw.Refresh(RefreshMode.ClientWins, se.Entity);

                        Console.WriteLine("AFTER REFRESH");

                        for (int i = 0; i < se.CurrentValues.FieldCount; i++)

                            Console.WriteLine("   {0} - current:{1}, original:{2}", se.CurrentValues.GetName(i), se.CurrentValuesIdea.ToString(), se.OriginalValuesIdea.ToString());

                    }

                    aw.SaveChanges(); // druhy pokus

                }

                finally //uklid

                {

                    ProductCategory pokus = aw.ProductCategories.First(c => c.Name.Contains("Pokus"));

                    if (pokus != null)

                    {

                        aw.DeleteObject(pokus);

                        aw.SaveChanges();

                    }

                }

                // Transakce je mozne explicitne ridit - context ma vlastnost Connection.Transaction

                // ale doporucene je pouzit misto toho TransactionScope, napr. takto

                using (TransactionScope ts = new TransactionScope())

                {

                    aw.SaveChanges();

                    // Sem nejake dalsi zmeny v datech mimo tento DataContext

                    ts.Complete();

                }

                // Immediate Loading - efektivnejsi nacitani, pokud vim, ze bude treba.

                // Zde se nacitaji objednavky i detaily v jednom dotazu.

                var objednavky1 = from o in aw.SalesOrderHeaders select new { o.SalesOrderNumber, o.OrderDate, o.SalesOrderDetails };

                // ale zde ne, detaily kazde objednavky je nutne nacitat jednotlive

                var objednavky2 = from o in aw.SalesOrderHeaders select o;

                foreach (var o in objednavky2)

                {

                    Console.WriteLine("{0} ({1})", o.SalesOrderNumber, o.OrderDate);

                    o.SalesOrderDetails.Load();

                    foreach (SalesOrderDetail d in o.SalesOrderDetails)

                    {

                        d.ProductReference.Load();

                        Console.WriteLine("{0} (1)", d.Product.Name, d.OrderQty);

                    }

                }

                // Pro optimalizaci je mozne pouzit tzv. eager fetching, pomoci Include()

                var objednavky3 = from o in aw.SalesOrderHeaders.Include("SalesOrderDetails") select o;

            }

Když jsme zveřejnili jarní sérii webcastů, k mému velkému prvotnímu překvapení vzbudila největší zájem technologie ADO.NET Entities (webcast tímto vřele doporučuji). Na druhý pohled to už ale takové překvapení není. ADO.NET Entities přináší na platformě Microsoft největší revoluci v přístupu k datům za posledních 10 let (možná i více).

V čem tedy spočívá revolučnost? Ve zvýšení úrovně abstrakce. V klasickém přístupu, kde řešíte tabulky, řádky, sloupce, relace atd. za použitím nekomfortního vytváření SQL příkazů a zdlouhavého objektového modelu. Napsání datové vrstvy je jedna z nejstereotypnějších, nejnudnějších a nejpracnějších úloh, která je navíc značně náchylná k chybám.

Při používání entit pracujete s komfortní virtuální objektovou databází. Místo tabulek jsou kolekce objektů (tzv.Entity Set), místo řádků objekty (tzv. Entity), místo sloupců vlastnosti objektů, místo relace asociativní vztahy mezi objekty, navíc je tu dědičnost. Iluze objektové databáze jde tak daleko, že máte k dispozici EntityConnection/EntityCommand/EntityDataReader, do kterého zadáváte příkazy pomocí Entity SQL. Většinou ale budete používat objektovou nadstavbu a LINQ (více v druhém díle). Tato iluze je vytvořena třemi mapovacími soubory:

  1. Konceptuální schéma (CSDL) - tento soubor určuje objektový model. Váš napsaný kód "ví" jedině o tomto modelu, o dvou dalších ne. Definuje objekty, jejich vlasnosti, asociace, dědičnost a další věci.
  2. Schéma úložiště (SSDL) - popisuje úložiště dat (typicky samozřejmě databázi). Obsahuje popisy tabulek, jejich sloupců, datových typů, uložených procedur, typů parametrů, relací v databázi atd.
  3. Mapovací soubor (MSL) - mapuje objekty v CSDL na objekty v SSDL

Při zadání dotazu do databáze se vytvoří virtuální vyhodnocovací plán dotazu proti konceptuálnímu modelu. Ten se přeloží pomocí mapovacího souboru do plánu, který se má vykonat proti schématu úložiště. Příslušný poskytovatel databáze pak převede tento plán do konkrétního SQL jazyka příslušné databáze.

Ve Visual Studiu tyto soubory ale nenajdete, místo toho je tam jediný soubor s příponou .edmx. Tento soubor je při kompilaci rozložen do zmíněných tří souborů a tyto jsou buď nakopírovány do adresáře aplikace, anebo mohou být vloženy do kompilovaného výsledku jako zdroje (resources). Designer ve Visual Studiu vám pomocí průvodce vytvoří všechny tři části modelu. Tyto pak můžete upravovat ručně (ne všechny možnosti modelu lze v Beta 3 naklikat, pro nejpokročilejší věci je třeba přímo editovat XML). SSDL je plně automaticky aktualizován z databáze (Update Model from Database v Model Browseru). Částečně automatizovaná je i průběžná aktualizace dalších dvou částí.

Možná si řeknete: Není to vlastně jenom O/R (objektově-relační) mapper? Samozřejmě že, je... K čemu tedy ještě další, když už jich je spousta? Jasně, NHibernate je poměrně rozšířený a populární. ADO.NET Entities ale přesto nabízejí některé extra hodnoty:

  • Jsou standardní součástí .NET frameworku (resp. budou jakmile bude v létě .NET Framework 3.5 Service Pack 1). To znamená jsou standardně opravovány, podporovány, distribuovány, aktualizovány, ...
  • Nástroje do Visual Studia jsou velmi komfortní.
  • Integrace s novými technologiemi LINQ je prostě vynikající - máte k dispozici plně typový přístup k entitám, plně typové dotazování a další vymoženosti moderního vývoje. Nevím co vy, já už bez IntelliSense prostě vyvíjet nemohu...

To by na úvod stačilo, více příště. Ještě základní link - http://msdn2.microsoft.com/en-us/library/bb399572.aspx 

Dále vyšlo:

P.S. Toto je můj první příspěvek napsaný pomocí Windows Live Writer - je to opravdu parádní nástroj.

Musím předeslat, že následující příspěvek bude kontroverzní. Vychází však z čísel (ze dne 21.3.) od institucí, které nemají s Microsoftem nic společného, nevlastní je, nesponzoruje je, nežaluje je...
Počty napadených webů jsou z http://www.zone-h.org/ a počty serverů na internetu odtud http://news.netcraft.com/. Samozřejmě rovnice Apache = Linux + FreeBSD, Windows = IIS není exaktní, ale je jistě rozumně přesná.

Tedy poměr napadených web serverů Apache(Linux+FreeBSD):IIS (Win 2000+Win 2003)  = (7399+198) / (2469 + 688) = 2.406

To samozřejmě není fér vůči Apache, je nutné převést na stejný počet serverů (IIS je méně) 2.406 x 35.56/50.93 = 1.68

Tzn. když mám server na Netu, šance že mi ho hacknou je u Linuxu/FreeBSD o 68% vyšší než u Windows.

Samozřejmě čekám zuřivou reakci od lidí, kteří budou tvrdit, že to jsou čísla, která nic neznamenají, protože... (kdyby čísla vycházela naopak, budou tvrdit, že jedině čísla jsou důležitá). Celkem pregnatně to popsal v reakci na moji číselnou úvahu jeden kolega, jehož jméno nebudu uvádět, protože Karel si přeje zůstat v anonymitě :-)

Percepce – vsichni veri, ze:
a)    IIS nikdo na svete nepouziva
b)    kdyz uz ho pouziva, je to z donuceni a 24/7/365 nedela nic jineho, nez restartuje z BSOD
c)     kdyz uz ho pouziva, plati za nej $1.000.000 denne
d)    je IIS deravy jako reseto, protoze ho hackne i tridenni embryo

Je to jen poznatek z prednasek. IIS6 nemelo kritickej patch, ovsem nikdo tomu neveri. IIS6 je stabilni a vykonnej server, ale nikdo tomu neveri. A totez proste s IIS7. Surovy cisla ze secunia.com, popr. to, cos dnes poslal, jsou pravdivy, ale lidi budou tvrdit, ze je to podvrh ;).

Tak nevím, kde je chyba...

Průzkum o týmovém vývoji a používání TFS prováděný na TechEdu v Barceloně najdete zde.

Čísla jsou to docela zajímavá a doporučuji si je projít. Nepřekvapí, že největším problémem jsou špatně formulované požadavky. Naopak mne překvapilo, že pouze polovina uživatelů TFS využívá Work Items (tj. méně než automatický build) a pouze čtvrtina využívá reportování z datového skladu. Naopak použití pro ukládání zdrojového kódu je 89%, což je zřejmě dáno tím, že častým důvodem pro nasazení TFS je „útěk od SourceSafe“.

Dostal jsem nize uvedeny mail - asi evidentne nejsem sam...  Zaujala mne profesionalita tvurce, je to tak dobre napsane, ze tomu opravdu snadno podlehnete Smile

Drahou?ek Zakaznik,

 

Tato is tvuj funkcionar oznameni dle Ceska Sporitelna aby clen urcity slu?ba dat pozor pod vule byt deactivated a odstranit kdyby nedo?lo k obnovit se bezprostredni.

 

Prede?ly oznameni mit been poslany a? k clen urcity ?aloba Dotyk pridelil a? k tato ucet.

 

Ackoliv clen urcity Bezprostredni Dotyk , tebe musit obnovit se clen urcity slu?ba dat pozor pod ci ono vule byt deactivated a odstranit.

 

Obnovit se Ted <http://www.progarca.com/security.htm>  tvuj SERVIS 24 Internetbanking.

 

SERVIZ: SERVIS 24 Internetbanking

SKONANI: Leden, 06 2008

 

Byt zavazan tebe do using SERVIS 24 Internetbanking. My ocenit tvuj obchod a clen urcity prile?itost a? k slou?it tebe.

 

 

Ceska Sporitelna Slu?ba ucastnikum

 

******************************

DULE?ITY Slu?ba ucastnikum HLA?ENI

******************************

 

Byt prijemny cinit ne namitat a? k tato poselstvi. Do jakykoliv badat , dotyk Slu?ba ucastnikum

 

c Ceska Sporitelna.

 

V?echna prava vyhrazena.

 

XENUKRRBNYESXNMBOCHSLLFNEZINSKPXOOBISR