<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blog.aspnet.sk/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Duracellko.NET</title><link>http://blog.aspnet.sk/duracellko/default.aspx</link><description>Vyvojársky blog od duracellka.. hlavne ohľadom .NET</description><dc:language>sk-SK</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Scrum Planning Poker pre Windows Azure</title><link>http://blog.aspnet.sk/duracellko/archive/2012/11/21/scrum-planning-poker-pre-windows-azure.aspx</link><pubDate>Wed, 21 Nov 2012 11:59:00 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:307332</guid><dc:creator>duracellko</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=307332</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2012/11/21/scrum-planning-poker-pre-windows-azure.aspx#comments</comments><description>&lt;p&gt;Ak na projektoch reálne používate Scrum, tak pojem Planning Poker určite poznáte. Ide o techniku odhadovania pracnosti/zložitosti bez toho, aby sa&amp;nbsp;jednotliví členovia tímu navzájom&amp;nbsp;ovplyvňovali. Viac o tejto hre môžete nájsť na &lt;a href="http://en.wikipedia.org/wiki/Planning_poker"&gt;wikipedii&lt;/a&gt;. Planning Poker je reálna hra, ktorá sa hrá s reálnymi kartami. Samozrejme že nie s mariášovými, ale sú na to špeciálne určené karty. Problém nastáva, keď vývojársky tím je distribuovaný a teda nemá možnosť sa fyzicky stretnúť. Práve pre tento účel som vytvoril Planning Poker web aplikáciu. Jediné, čo k tomu potrebujete, je:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div&gt;Webový prehliadač&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Samozrejme nejaké komunikovadlo medzi členmi tímu. Niečo na&amp;nbsp;konferenčný hovor, prípadne video konferenčný hovor.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;A niekde hostovať webovú aplikáciu Planning Poker.&amp;nbsp;Hoci aj na Windows Azure.&amp;nbsp;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Keďže samotná aplikácia môže byť zaujímavá aj z pohľadu vývoja a je to v podstate moja prvá aplikácia pre Windows Azure, tak celý projekt môžete nájsť na &lt;a href="http://www.codeplex.com"&gt;CodePlexe&lt;/a&gt;. Takže nech sa páči &lt;a href="http://planningpoker4azure.codeplex.com/"&gt;Planning Poker 4 Azure&lt;/a&gt;.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=307332" width="1" height="1"&gt;</description></item><item><title>CustomValidationAttribute nie je thread-safe</title><link>http://blog.aspnet.sk/duracellko/archive/2011/06/23/customvalidationattribute-nie-je-thread-safe.aspx</link><pubDate>Thu, 23 Jun 2011 20:29:22 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:306951</guid><dc:creator>duracellko</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=306951</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2011/06/23/customvalidationattribute-nie-je-thread-safe.aspx#comments</comments><description>&lt;p&gt;Nedávno som narazil na chybičku v CustomValidationAttribute. A to konkrétne, že inicializačná procedúra v tejto triede nie je thread-safe. Presnejšie na začiatku tejto procedúry sa nastaví flag, že inicializácia už prebehla. Avšak ak medzitým nejaký iný thread validuje inú inštanciu tej istej triedy, tak si myslí že inicializácia už prebehla a pri spustení validačnej metódy vznikne NullReferenceException. A presne toto sa stalo mne.&lt;/p&gt;  &lt;p&gt;Tento scenár sa vám asi ťažko podarí spraviť v nejakej webovej aplikácii. To by muselo niekoľko užívateľov naraz uložiť záznam rovnakého typu a aj to po spustení aplikácie. Ak sa to totiž raz podarí, tak atribút zostane inicializovaný až do ukončenia aplikácie.&lt;/p&gt;  &lt;p&gt;Preto mne sa podarilo na túto chybu naraziť až keď som robil job, ktorý synchronizuje dáta v aplikácii. A aby to bežalo rýchlejšie, tak každý záznam sa synchronizuje paralelne cez Parallel.ForEach. A práve tu už nebol problém naraziť na NullReferenceException.&lt;/p&gt;  &lt;p&gt;Bližší popis chyby je na connecte: &lt;a title="http://connect.microsoft.com/VisualStudio/feedback/details/675788/customvalidationattribute-is-not-thread-safe" href="http://connect.microsoft.com/VisualStudio/feedback/details/675788/customvalidationattribute-is-not-thread-safe"&gt;http://connect.microsoft.com/VisualStudio/feedback/details/675788/customvalidationattribute-is-not-thread-safe&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Nájdete tu aj zdrojový kód programu, ktorý presne túto chybu simuluje.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=306951" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/DataAnnotations/default.aspx">DataAnnotations</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/Validation/default.aspx">Validation</category></item><item><title>Clipboard Share alebo môj prvý open-source projekt</title><link>http://blog.aspnet.sk/duracellko/archive/2010/02/12/clipboard-share-alebo-m-244-j-prv-253-open-source-projekt.aspx</link><pubDate>Fri, 12 Feb 2010 14:35:18 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:291904</guid><dc:creator>duracellko</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=291904</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2010/02/12/clipboard-share-alebo-m-244-j-prv-253-open-source-projekt.aspx#comments</comments><description>&lt;p&gt;Nedávno som dostal požiadavku na programček na posielanie obsahu clipboardu medzi počítačmi od človeka, ktorý používa viac počítačov naraz. Celkom jednoduchý programček s použitím WCF. Práve pri tom vznikol článok &lt;a href="http://blog.aspnet.sk/duracellko/archive/2010/01/25/wcf-service-na-vo-nom-tcp-porte.aspx"&gt;WCF service na voľnom TCP porte&lt;/a&gt;. Obsah sa pri posielaní šifruje a podpíše. Potom je možné prijať obsah clipboardu len od dôveryhodných odosielateľov.&lt;/p&gt;  &lt;p&gt;Trochu bol problém zistiť zoznam počítačov, na ktorých beží tento programček. Práve na to som použil &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.netpeertcpbinding.aspx"&gt;Net Peer Binding&lt;/a&gt; vo WCF.&lt;/p&gt;  &lt;p&gt;A keďže je úplne zbytočné niečo spraviť, keď sa o to človek nepodelí, tak som sa rozhodol to dať na &lt;a href="http://www.codeplex.com/"&gt;CodePlex&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;A samotný Clipboard Share nájdete &lt;a href="http://clipboardshare.codeplex.com/"&gt;tu&lt;/a&gt;.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=291904" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/WinForms/default.aspx">WinForms</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/Clipboard+Share/default.aspx">Clipboard Share</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/Open+source/default.aspx">Open source</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/CodePlex/default.aspx">CodePlex</category></item><item><title>ObservableCollection</title><link>http://blog.aspnet.sk/duracellko/archive/2010/02/06/observablecollection.aspx</link><pubDate>Sat, 06 Feb 2010 16:01:30 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:282472</guid><dc:creator>duracellko</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=282472</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2010/02/06/observablecollection.aspx#comments</comments><description>&lt;p&gt;Čo sa za mladi naučíš, v starobe ako by si našiel. Tak toto som našiel celkom neskoro. Už niekoľkokrát som potreboval kolekciu s udalosťami o pridaní a odobraní prvku. Napísať si takú kolekciu podedením z triedy &lt;a href="http://msdn.microsoft.com/en-us/library/ms132397.aspx"&gt;Collection&amp;lt;T&amp;gt;&lt;/a&gt; nie je žiadny problém. Lenže načo niečo také, keď v .NET od verzie 3.0 máme triedu &lt;a href="http://msdn.microsoft.com/en-us/library/ms668604.aspx"&gt;ObservableCollection&amp;lt;T&amp;gt;&lt;/a&gt;. A tá obsahuje dve udalosti.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;CollectionChanged&lt;/strong&gt; sa vyvolá, keď sa zmení kolekcia. Teda, keď tam pridáme, odoberieme prvok, zmeníme na určitej pozícii alebo vyčistíme kolekciu.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;PropertyChanged&lt;/strong&gt; sa vyvolá, keď sa zmení nejaký objekt v kolekcii. Toto funguje, iba ak objekty v kolekcii implementujú interface &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx"&gt;INotifyPropertyChanged&lt;/a&gt;.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;A túto triedu som doteraz poctivo ignoroval práve preto, že je v netradičnej assembly WindowsBase, ktorú si spájam práve s WPF. Ale v skutočnosti táto assembly súvisí hlavne so XAML, ktorý je oveľa univerzálnejší ako WPF. Napríklad sa dá použiť s Workflow Foundation.&lt;/p&gt;  &lt;p&gt;Ešte pre úplnosť, tak táto trieda je v namespace System.Collections.ObjectModel.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=282472" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/.NET/default.aspx">.NET</category></item><item><title>WCF service na voľnom TCP porte</title><link>http://blog.aspnet.sk/duracellko/archive/2010/01/25/wcf-service-na-vo-nom-tcp-porte.aspx</link><pubDate>Mon, 25 Jan 2010 13:44:22 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:260140</guid><dc:creator>duracellko</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=260140</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2010/01/25/wcf-service-na-vo-nom-tcp-porte.aspx#comments</comments><description>&lt;p&gt;Nedávno som robil jednoduchú desktopovú aplikáciu, ktorá prenáša dáta medzi užívateľmi. Niečo ako instant messaging, len sa neprenášajú užívateľom písané správy. Keďže aplikácia nemusí fungovať cez internet, stačí len na LAN, tak som sa rozhodol použiť WCF a NetTcpBinding.&lt;/p&gt;  &lt;p&gt;A keďže je to desktopová aplikácia a môj protokol nie je žiaden štandard, tak som nevyhradil žiaden špecifický TCP port, na ktorom by služba počúvala. Ale narazil som na problém, že donútiť WCF službu počúvať na ľubovoľnom voľnom porte a ešte zistiť ten port nie je celkom jednoduché. Našťastie je to možné a nie je to žiadna tragédia.&lt;/p&gt;  &lt;p&gt;Najprv na NetTcpBinding musíme nastaviť nejaký špecifický namespace aj name. Potom po pridaní ServicePoint do ServiceHost nastavíme na ServicePoint ListenUriMode na Unique. Toto zabezpečí, že WCF služba bude fungovať na ľubovoľnom voľnom TCP porte.&lt;/p&gt;  &lt;p&gt;A po spustení ServiceHost vyhľadáme ChannelDispatcher s príslušným name a namespace. A potom už stačí len zobrať Lister Uri a z nej prečítať port.&lt;/p&gt;  &lt;p&gt;Tu je kód ako to spraviť.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;// vytvorim novy ServiceHost&lt;/p&gt;    &lt;p&gt;var host = new ServiceHost(new MyService(), new Uri(“net.tcp://localhost/MyService”));&lt;/p&gt;    &lt;p&gt;// nastavim TCP binding&lt;/p&gt;    &lt;p&gt;var binding = new NetTcpBinding();&lt;/p&gt;    &lt;p&gt;binding.Namespace = “MyNamespace”;&lt;/p&gt;    &lt;p&gt;binding.Name = “MyServiceBinding”;&lt;/p&gt;    &lt;p&gt;// pridam a nastavim ServicePoint&lt;/p&gt;    &lt;p&gt;var sp = host.AddServicePoint(typeof(IMyService), binding, String.Empty);&lt;/p&gt;    &lt;p&gt;sp.ListenUriMode = ListenUriMode.Unique;&lt;/p&gt;    &lt;p&gt;// spustime sluzbu&lt;/p&gt;    &lt;p&gt;host.Open();&lt;/p&gt;    &lt;p&gt;// zistim TCP post&lt;/p&gt;    &lt;p&gt;var channelDispatcher = host.ChannelDispatchers.OfType&amp;lt;ChannelDispatcher&amp;gt;().FirstOrDefault(cd =&amp;gt; cd.BindingName == “MyNamespace:MyServiceBinding”);&lt;/p&gt;    &lt;p&gt;int port = 0;&lt;/p&gt;    &lt;p&gt;if (channelDispatcher != null)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160; port = channelDispatcher.Listener.Uri.Port;&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Alebo ak máte radšej zápis pre konfiguračný súbor.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;&amp;lt;system.serviceModel&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160; &amp;lt;services&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;service name=”MyService”&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;host&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;baseAddresses&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;baseAddress baseAddress=”net.tcp://localhost/MyService”/&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/baseAddresses&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/host&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;endpoint binding=”netTcpBinding” bindingNamespace=”MyNamespace” bindingName=”MyServiceBinding” listenUriMode=”Unique” /&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/service&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;#160; &amp;lt;/services&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;lt;/system.serviceModel&amp;gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Takto máme službu, ktorá sa vždy otvorí na náhodnom porte. Predpokladajme, že sa nám podarí toto číslo portu dostať na klienta. Ja som na to použil NetPeerTcpBinding kanál. Celkom sranda vecička, ale o tom inokedy. Keďže klient vie port pre daný počítač, tak nie je problém poskladať URI a pripojiť sa na WCF službu. No na moje prekvapenie to trochu problém je. Je totiž rozdiel medzi URI, ktorá identifikuje službu, a URI, na ktorej služba fyzicky beží.&lt;/p&gt;  &lt;p&gt;URI, ktorá identifikuje službu, je tá, ktorú zadávame pri vytváraní endpointu (alebo servicepointu). V našom prípade je to base address, ktorú sme zadali pri vytvorení ServiceHost.&lt;/p&gt;  &lt;p&gt;Fyzická URI je tá, ktorú musíme zadať klientovi, aby vedel, kam sa má pripojiť. V našom prípade to bude URI so správnym názvom počítača a uvedeným TCP portom. Napr.: net.tcp://duracellkopc:12345/MyService&lt;/p&gt;  &lt;p&gt;A tu je kameň úrazu. WCF štandardne predpokladá, že obidve URI sú rovnaké. Teda až na názov počítača. To je jediná časť URI, ktorá sa ignoruje, avšak aj toto sa dá zmeniť. Takže klient vytvorí TCP spojenie a pošle požiadavku na službu so špecifickou URI. Lenže WCF na serverovej strane povie, že žiadnu službu na URI s takým portom nepozná.&lt;/p&gt;  &lt;p&gt;Našťastie aj pri klientovi sa dá povedať, že má pristupovať k službe s určitou URI, ale fyzicky sa má pripojiť niekam inam. A to niekam inam sa vo WCF nazýva ClientViaBehavior. Čiže konštruktor pre klienta by bol asi takýto.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;public MyServiceClient(Uri remoteAddress)&lt;/p&gt;    &lt;p&gt;&amp;#160; : base(new NetTcpBinding(), GetPortLessUri(remoteAddress))&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160; Endpoint.Behaviors.Add(new ClientViaBehavior(remoteAddress));&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;private static Uri GetPortLessUri(Uri uri)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160; var uriBuilder = new UriBuilder(uri);&lt;/p&gt;    &lt;p&gt;&amp;#160; uriBuilder.Port = –1;&lt;/p&gt;    &lt;p&gt;&amp;#160; return uriBuilder.Uri;&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Tak a máme službu, ktorá beží na ľubovoľnom voľnom porte a zároveň aj klienta, ktorý sa na ňu vie pripojiť.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=260140" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/WCF/default.aspx">WCF</category></item><item><title>Ako zobraziť okno bez focusu</title><link>http://blog.aspnet.sk/duracellko/archive/2010/01/21/ako-zobrazi-okno-bez-focusu.aspx</link><pubDate>Wed, 20 Jan 2010 23:29:06 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:245798</guid><dc:creator>duracellko</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=245798</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2010/01/21/ako-zobrazi-okno-bez-focusu.aspx#comments</comments><description>&lt;p&gt;Toto je rýchly blog, aby som to nemusel googliť zase niekoľko hodín.&lt;/p&gt;  &lt;p&gt;Jedna možnosť je overide vlastnosti &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.form.showwithoutactivation(VS.80).aspx"&gt;ShowWithoutActivation&lt;/a&gt;. Stačí, aby táto vlastnosť vrátila true a okno nebude mať focus pri otvorení. Problém je, že toto nefunguje pri TopMost formách. Avšak našiel som pekný trik. Overide vlastnosti &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.form.createparams(VS.80).aspx"&gt;CreateParams&lt;/a&gt;. Táto vlastnosť vytvorí argumenty, ktoré sa pošlú funkcii CreateWindowEx. Toto ponúka celkom dosť možností. A hlavne nastaviť štýl okna na WS_EX_NOACTIVATE. Tento štýl znamená, že okno nebude mať nikdy focus, ani keď užívateľ na neho klikne. Tento štýl sa používa na floating toolbars a podobne okná, keď užívateľ klikne na gombík na toolbare, ale focus má stále hlavné okno.&lt;/p&gt;  &lt;p&gt;Ja som toto použil pri vlastnej notifikácii nad ikonou v system tray. A tu je kód.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;protected override CreateParams CreateParams&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; get&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CreateParams result = base.CreateParams;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; result.ExStyle |= WinApi.WS_EX_NOACTIVATE;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return result;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Ešte pre úplnosť, tak WS_EX_NOACTIVE = 0x08000000. Toto je možné zistiť na stránke &lt;a href="http://www.pinvoke.net"&gt;www.pinvoke.net&lt;/a&gt;. Mimochodom veľmi dobrá stránka ak potrebujete volať WinAPI z .NET.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=245798" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/WinForms/default.aspx">WinForms</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Task Parallel Library a .NET 4.0</title><link>http://blog.aspnet.sk/duracellko/archive/2009/10/27/task-parallel-library-a-net-4-0.aspx</link><pubDate>Tue, 27 Oct 2009 12:59:16 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:144224</guid><dc:creator>duracellko</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=144224</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2009/10/27/task-parallel-library-a-net-4-0.aspx#comments</comments><description>&lt;p&gt;S TPL som sa hral už, keď vyšla prvá verzia CTP. TPL je framework, ktorý má uľahčiť vývoj algoritmov optimalizovaný pre viac jadrové procesory. A v dokumentácii som sa dočítal, že CTP nevytvorí viac threadov, ako je jadier v procesoroch. Teda threadov môže byť viac, ale nespiacich by nemalo byť viac. Je to celkom rozumná podmienka, pretože v skutočnosti nemôže bežať paralelne viac threadov ako procesorov. Každý ďalší thread sa musí deliť o procesor, a teda dochádza k prepínaniu threadov, čiže v skutočnosti nebežia paralelne, len sa veľmi rýchlo striedajú.&lt;/p&gt;  &lt;p&gt;Než budem pokračovať, tak najprv musím zadefinovať dve veci. Je to čisto moja definícia, ktorú som už párkrát písal na aspnet.sk.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Paralelný algoritmus&lt;/strong&gt; – algoritmus, ktorý využíva viac procesorov. Čiže sa skladá z úloh, ktoré môžu bežať naraz na viacerých procesoroch. Avšak každá takáto úloha využíva len procesor a pamäť. Žiadne iné zdroje ako disk, databázu, web services nepoužíva. Napríklad paralelné triedenie alebo raytracing.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Asynchrónna úloha&lt;/strong&gt; – úloha, ktorá sa má spustiť na pozadí a hlavný proces môže vykonávať niečo iné, pokiaľ sa úloha vykonáva. Typický príklad je asynchrónne volanie web service. Web service sa zavolá na pozadí a hlavný program beží ďalej a nie je zamrznutý.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Tieto definície som si zaviedol po zoznámení sa s TPL CTP1. A taktiež všeobecná poučka hovorila, že TPL je určené práve na paralelné algoritmy a nie asynchrónne úlohy. Paralelné algoritmy využívajú len procesor, a práve preto nemá význam aby sa spúšťalo viac úloh paralelne, ako je procesorov. Proste celý algoritmus nemôže bežať rýchlejšie, ale skôr pomalšie, lebo aj context switch niečo stojí. A na jednojadrovom procesore by mal bežať algoritmus úplne sekvenčne.&lt;/p&gt;  &lt;p&gt;Naopak asynchónnych úloh môžem mať spustených oveľa viac ako je procesorov. Veď aj tak každý thread spí a čaká, kým sa niečo dokončí na nejakom inom zariadení (napríklad na servery, kde beží web service).&lt;/p&gt;  &lt;p&gt;Práve preto TPL CTP bola určená na paralelné algoritmy, ale nebola vôbec vhodná na asynchrónne úlohy. Lenže toto sa zmenilo v .NET 4.0. Najprv som si všimol, že v MSDN okrem klasických príkladov na paralelné násobenie matíc pribudli aj príklady na asynchrónne volanie web service. A na stránke &lt;a href="http://msdn.microsoft.com/en-us/library/dd997419(VS.100).aspx"&gt;Introduction to Tasks&lt;/a&gt; píšu, že úlohy sú plánované pre maximálnu priepustnosť, ale nič o tom, že by počet threadov bol obmedzený počtom procesorov. Dokonca tam píšu, že celé je to postavené na klasickom .NET ThreadPool, aj keď som niekde čítal, že ten bol prepísaný. História bola asi taká, že v CTP1 to bolo postavené na ThreadPool, potom v CTP2 si napísali vlastný plánovač a asi na základe neho prepísali ThreadPool v .NET 4.0.&lt;/p&gt;  &lt;p&gt;Tak som sa rozhodol overiť, ako to je s tým počtom threadov. Spravil som si jednoduchú funkciu, ktorá opakuje cyklus, kým ubehne 15 sekúnd. A túto funkciu som pustil 15-krát paralelne.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;private static void WaitTasks()&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; var time = new TimeSpan(0, 0, 15);&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Parallel.For(0, 15, i =&amp;gt; Wait(time, i));&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;private static void Wait(TimeSpan time, int id)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; var startTime = DateTime.Now;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;Task {0} starts at {1:hh:MM:ss.ff}... {2}&amp;quot;, id, startTime, Task.CurrentId);&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; var now = DateTime.Now;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; while (now &amp;lt; startTime + time)&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; now = DateTime.Now;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;Task {0} ends at {1:hh:MM:ss.ff}... {2}&amp;quot;, id, DateTime.Now, Task.CurrentId);&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;A výsledok bol asi nasledovný:&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;Task 0 starts at 01:10:06.63... 1&lt;/p&gt;    &lt;p&gt;Task 7 starts at 01:10:06.69... 2&lt;/p&gt;    &lt;p&gt;Task 14 starts at 01:10:07.88... 3&lt;/p&gt;    &lt;p&gt;Task 1 starts at 01:10:10.43... 4&lt;/p&gt;    &lt;p&gt;Task 8 starts at 01:10:14.31... 5&lt;/p&gt;    &lt;p&gt;Task 2 starts at 01:10:18.90... 6&lt;/p&gt;    &lt;p&gt;Task 0 ends at 01:10:21.83... 1&lt;/p&gt;    &lt;p&gt;Task 3 starts at 01:10:21.83... 1&lt;/p&gt;    &lt;p&gt;Task 7 ends at 01:10:22.20... 2&lt;/p&gt;    &lt;p&gt;Task 9 starts at 01:10:22.20... 7&lt;/p&gt;    &lt;p&gt;Task 14 ends at 01:10:22.90... 3&lt;/p&gt;    &lt;p&gt;Task 5 starts at 01:10:22.90... 8&lt;/p&gt;    &lt;p&gt;Task 1 ends at 01:10:25.95... 4&lt;/p&gt;    &lt;p&gt;Task 11 starts at 01:10:25.95... 9&lt;/p&gt;    &lt;p&gt;Task 8 ends at 01:10:29.66... 5&lt;/p&gt;    &lt;p&gt;Task 13 starts at 01:10:29.66... 10&lt;/p&gt;    &lt;p&gt;Task 2 ends at 01:10:34.47... 6&lt;/p&gt;    &lt;p&gt;Task 3 ends at 01:10:36.83... 1&lt;/p&gt;    &lt;p&gt;Task 4 starts at 01:10:36.83... 1&lt;/p&gt;    &lt;p&gt;Task 9 ends at 01:10:37.30... 7&lt;/p&gt;    &lt;p&gt;Task 10 starts at 01:10:37.30... 7&lt;/p&gt;    &lt;p&gt;Task 5 ends at 01:10:38.25... 8&lt;/p&gt;    &lt;p&gt;Task 6 starts at 01:10:38.25... 8&lt;/p&gt;    &lt;p&gt;Task 11 ends at 01:10:40.95... 9&lt;/p&gt;    &lt;p&gt;Task 12 starts at 01:10:40.95... 9&lt;/p&gt;    &lt;p&gt;Task 13 ends at 01:10:45.11... 10&lt;/p&gt;    &lt;p&gt;Task 4 ends at 01:10:51.86... 1&lt;/p&gt;    &lt;p&gt;Task 10 ends at 01:10:52.34... 7&lt;/p&gt;    &lt;p&gt;Task 6 ends at 01:10:53.26... 8&lt;/p&gt;    &lt;p&gt;Task 12 ends at 01:10:55.95... 9&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Takže je vidno, že až 5 threadov bežalo paralelné, aj keď nezačali všetky naraz, ale ThreadPool chvíľu čakal, či sa mu nejaký thread neuvoľní. Je to vidieť aj na nasledovnom obrázku.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.aspnet.sk/blogs/duracellko/threads_0CDE90C5.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="threads" border="0" alt="threads" src="http://blog.aspnet.sk/blogs/duracellko/threads_thumb_2EC9F349.png" width="644" height="249" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Potom som ešte spravil to, že som rovnakú funkcionalitu prepísal pomocou Delegate.BeginInvoke, čo využíva ThreadPool a je v .NET už od verzie 1.0.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;private static void WaitThreads()&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; var time = new TimeSpan(0, 0, 15);&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; var waitDelegates = new Action&amp;lt;int&amp;gt;[15];&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; var waitAsyncResults = new IAsyncResult[waitDelegates.Length];&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; for (int i = 0; i &amp;lt; waitDelegates.Length; i++)&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; waitDelegates[i] = id =&amp;gt; Wait(time, id);&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; waitAsyncResults[i] = waitDelegates[i].BeginInvoke(i, null, null);&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; WaitHandle.WaitAll(waitAsyncResults.Select(ar =&amp;gt; ar.AsyncWaitHandle).ToArray());&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Výsledok bol ten istý. Tiež sa vytvorilo 5 threadov a aj časy boli rovnaké.&lt;/p&gt;  &lt;p&gt;Aby som to celé zhrnul, tak som bol vždy toho názoru (spolu s Vlkom), že s TPL v mojej praxi veľmi do styku neprídem a podobne je na tom so mnou väčšina programátorov. Veď koľkí z vás programujú násobenie matic alebo iné paralelné algoritmy. Zato jednoduché asynchrónne volanie webservice je asi problémom väčšiny z nás. A keďže prístup TPL sa v .NET 4.0 zmenil, tak aj ja musím zmeniť svoj názor. Proste TPL je už vhodná aj na asynchrónne úlohy a stačí si porovnať v mojom príklade funkcie WaitTasks a WaitThreads.&lt;/p&gt;  &lt;p&gt;Žiaľ neexistuje na MSDN článok o TaskScheduler, že ako to je s jeho optimalizáciou práve pre paralelné algoritmy. Zatiaľ je tam len To Be Done.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=144224" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blog.aspnet.sk/duracellko/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category></item><item><title>Stream.CopyTo</title><link>http://blog.aspnet.sk/duracellko/archive/2009/10/25/stream-copyto.aspx</link><pubDate>Sun, 25 Oct 2009 16:56:01 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:143499</guid><dc:creator>duracellko</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=143499</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2009/10/25/stream-copyto.aspx#comments</comments><description>&lt;p&gt;Trochu som si pozeral to nové Visual Studio a veľmi ma potešila úplna maličkosť. Nová metóda &lt;strong&gt;Stream.CopyTo&lt;/strong&gt;. Aj preto, že určite každý ste si ju sami napísali aspoň raz. Jej funkciou je skopírovať obsah Stream-u do druhého Stream-u. A sú dve verzie.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;Stream.CopyTo(Stream destination);&lt;/p&gt;    &lt;p&gt;Stream.CopyTo(Stream destination, int bufferSize);&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;V tej druhej verzii môžete povedať, aký veľký buffer sa má pri kopírovaní použiť.&lt;/p&gt;  &lt;p&gt;Na MSDN to nájdete na &lt;a title="http://msdn.microsoft.com/en-us/library/system.io.stream.copyto(VS.100).aspx" href="http://msdn.microsoft.com/en-us/library/system.io.stream.copyto(VS.100).aspx"&gt;http://msdn.microsoft.com/en-us/library/system.io.stream.copyto(VS.100).aspx&lt;/a&gt;&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=143499" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/.NET/default.aspx">.NET</category></item><item><title>INNER JOIN cez dva stĺpce a OR</title><link>http://blog.aspnet.sk/duracellko/archive/2009/10/19/inner-join-cez-dva-st-pce-a-or.aspx</link><pubDate>Mon, 19 Oct 2009 08:36:54 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:141447</guid><dc:creator>duracellko</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=141447</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2009/10/19/inner-join-cez-dva-st-pce-a-or.aspx#comments</comments><description>&lt;p&gt;Tak je tu ďalšie T-SQL okienko. Tentoraz ide čisto len o problém na SQL Server. Možno na iných databázach sa query optimalizátor správa trochu inteligentnejšie. A možno aj nie :)&lt;/p&gt;  &lt;p&gt;Pracujem na systéme postavenom nad MS CRM, kde fyzické osoby sú uložené v entite contact a právnicke v entite account. Pre tých, ktorým MS CRM nič nehovorí, tak každá (alebo väčšina) entita je uložená v dvoch SQL tabuľkách, pričom tieto dve tabuľky sú spojené vo view s rovnakým názvom ako je názov entity. Každý objekt má primárny kľúč uniqueidentifier, teda GUID, takže každý objekt má jedinečné ID v rámci celej databázy.&lt;/p&gt;  &lt;p&gt;Ďalej som mal vo vedľajšej databáze v tabuľke zoznam klientov, ktorí sa majú nejak spracovať. Stačí zoznam GUID a typ, či ide o account alebo contact. Klient môže mať nejaké zmluvy, ktoré sú uložené v custom entite new_contract. Problém MS CRM je, že nad jedným stĺpcom môže byť len jeden foreign key. Takže new_contract obsahuje dva stĺpce new_account a new_contact, pričom vždy je vyplnený práve jeden z nich. A tu je kameň úrazu. Chcem vybrať všetky zmluvy klientov, ktorí sú v pomocnej databáze. Tak som spravil jednoduchý SELECT.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;SELECT *&lt;/p&gt;    &lt;p&gt;FROM ProcessClient PC INNER JOIN – zoznam klientov na spracovanie&lt;/p&gt;    &lt;p&gt;New_MSCRM.dbo.new_contract Cn ON Cn.new_account = PC.ClientId OR Cn.new_contact = PC.ClientId&lt;/p&gt;    &lt;p&gt;WHERE Cn.DeletionStateCode = 0&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Lenže tento príkaz, ktorý sa mal vykonať za sekundu trval niekoľko minút. Aj nad stĺpcom new_account aj new_contact existujú indexy. Tak som predpokladal, že query optimalizátor pre každého klienta vyhľadá zmluvy podľa jedného aj druhého indexu a potom tieto dve množiny zjednotí. Dokonca operácia zjednotenia by bola veľmi jednoduchá, lebo vždy by bola jedna množina prázdna. Lenže podľa query plan sa SQL Server vykašľal na oba indexy a robil full scan nad celou tabuľkou.&lt;/p&gt;  &lt;p&gt;Riešenie bolo rozdeliť podmienku OR do dvoch joinov.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;SELECT *&lt;/p&gt;    &lt;p&gt;FROM ProcessClient PC LEFT JOIN&lt;/p&gt;    &lt;p&gt;New_MSCRM.dbo.new_contract CnA ON CnA.new_account = PC.ClientId LEFT JOIN&lt;/p&gt;    &lt;p&gt;New_MSCRM.dbo.new_contract CnC ON CnC.new_contact = PC.ClientId&lt;/p&gt;    &lt;p&gt;WHERE ISNULL(CnA.DeletionStateCode, CnC.DeletionStateCode) = 0&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Problém bol v tom, že celý SELECT bol oveľa zložitejší a na zmluvy som mal naviazané ešte ďalšie tabuľky a tie by som musel tiež zdvojiť. Takže by sa celý príkaz stal zbytočne nečitateľný. Našťastie som si spomenul na čarovné slovíčko CROSS APPLY. Keď nevedel query optimalizátor spraviť UNION automaticky, tak mu ho treba napísať exaktne. Takže výsledok bol nasledovný.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;SELECT *&lt;/p&gt;    &lt;p&gt;FROM ProcessClient PC CROSS APPLY (&lt;/p&gt;    &lt;p&gt;SELECT * FROM New_MSCRM.dbo.new_contract CnA ON CnA.new_account = PC.ClientId&lt;/p&gt;    &lt;p&gt;UNION ALL&lt;/p&gt;    &lt;p&gt;SELECT * FROM New_MSCRM.dbo.new_account CnC ON CnC.new_contact = PC.ClientId&lt;/p&gt;    &lt;p&gt;) AS Cn&lt;/p&gt;    &lt;p&gt;WHERE Cn.DeletionStateCode = 0&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;A naozaj pomohlo. Vykonanie príkazu sa skrátilo na sekundu. Takže vyhnite sa OR operátorom v joinoch a naozaj funkčné a čitateľné riešenie je použiť UNION v CROSS APPLY.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=141447" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/SQL/default.aspx">SQL</category></item><item><title>T-SQL a výber prvej asociovanej položky</title><link>http://blog.aspnet.sk/duracellko/archive/2009/08/13/t-sql-a-v-253-ber-prvej-asociovanej-polo-ky.aspx</link><pubDate>Thu, 13 Aug 2009 07:51:35 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:128315</guid><dc:creator>duracellko</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=128315</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2009/08/13/t-sql-a-v-253-ber-prvej-asociovanej-polo-ky.aspx#comments</comments><description>&lt;p&gt;Po &lt;a href="http://blog.aspnet.sk/petersirka/archive/2009/08/11/t-sql-alebo-o-som-do-teraz-nevedel.aspx"&gt;Sirovom príspevku na T-SQL&lt;/a&gt; pridám aj ja niečo. Predstavte si, že máte dve tabuľky &lt;strong&gt;Contact&lt;/strong&gt; a &lt;strong&gt;PhoneNumber&lt;/strong&gt;.&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="1" style="width:400px;"&gt;     &lt;tr&gt;       &lt;td style="width:200px;vertical-align:top;"&gt;         &lt;table cellspacing="0" cellpadding="1"&gt;             &lt;tr&gt;               &lt;td&gt;&lt;strong&gt;Contact&lt;/strong&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr&gt;               &lt;td&gt;&lt;u&gt;ContactId&lt;/u&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr&gt;               &lt;td&gt;FirstName&lt;/td&gt;             &lt;/tr&gt;              &lt;tr&gt;               &lt;td&gt;LastName&lt;/td&gt;             &lt;/tr&gt;              &lt;tr&gt;               &lt;td&gt;ďalšie stĺpce&lt;/td&gt;             &lt;/tr&gt;           &lt;/table&gt;       &lt;/td&gt;        &lt;td style="width:200px;vertical-align:top;"&gt;         &lt;table cellspacing="0" cellpadding="1"&gt;             &lt;tr&gt;               &lt;td&gt;&lt;strong&gt;PhoneNumber&lt;/strong&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr&gt;               &lt;td&gt;&lt;u&gt;PhoneNumberId&lt;/u&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr&gt;               &lt;td&gt;ContactId&lt;/td&gt;             &lt;/tr&gt;              &lt;tr&gt;               &lt;td&gt;Number&lt;/td&gt;             &lt;/tr&gt;           &lt;/table&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/table&gt;  &lt;p&gt;Pričom ContactId v tabuľke PhoneNumber je foreign key na stĺpec ContactId z tabuľky Contact.&lt;/p&gt;  &lt;p&gt;A problém je nasledovný. Treba vybrať všetky kontakty a ku každému najviac jedno telefónne číslo. Je úplne jedno ktoré, ale najviac jedno. Určite väčšina z vás už podobný problém riešila. Ja používam už od čias mojich začiatkov s SQL nasledovné riešenie.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;WITH PhoneNumberMinId (ContactId, MinPhoneNumberId) AS&lt;/p&gt;    &lt;p&gt;(&lt;/p&gt;    &lt;p&gt;SELECT ContactId, MIN(PhoneNumberId) AS MinPhoneNumberId&lt;/p&gt;    &lt;p&gt;FROM PhoneNumber&lt;/p&gt;    &lt;p&gt;GROUP BY ContactId&lt;/p&gt;    &lt;p&gt;)&lt;/p&gt;    &lt;p&gt;SELECT C.*, PN.Number&lt;/p&gt;    &lt;p&gt;FROM Contact C LEFT JOIN&lt;/p&gt;    &lt;p&gt;PhoneNumberMinId PNMI ON PNMI.ContactId = C.ContactId LEFT JOIN&lt;/p&gt;    &lt;p&gt;PhoneNumber PN ON PN.PhoneNumberId = PNMI.MinPhoneNumberId&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Táto syntax sa dá použiť len v SQL Server 2005 a vyššej verzii, ale použil som ju kvôli lepšej čitateľnosti a zrozumiteľnosti. Pred SQL 2005 som používal nasledovný select, ktorý je sémanticky úplne rovnaký.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;SELECT C.*, PN.Number&lt;/p&gt;    &lt;p&gt;FROM Contact C LEFT JOIN&lt;/p&gt;    &lt;p&gt;(&lt;/p&gt;    &lt;p&gt;SELECT ContactId, MIN(PhoneNumberId) AS MinPhoneNumberId&lt;/p&gt;    &lt;p&gt;FROM PhoneNumber&lt;/p&gt;    &lt;p&gt;GROUP BY ContactId&lt;/p&gt;    &lt;p&gt;) AS PNMI ON PNMI.ContactId = C.ContactId LEFT JOIN&lt;/p&gt;    &lt;p&gt;PhoneNumber PN ON PN.PhoneNumberId = PNMI.MinPhoneNumberId&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Podobnú štruktúru mám teraz aj v MS CRM. Lenže MS CRM primárne kľúče nepoužíva Integer ale GUID. A SQL nepodporuje funkciu MIN nad GUID. Takže moje dlhoročné riešenie prestalo fungovať. Našťastie v SQL Server 2005 pribudli novinky, ktoré podobný problém dokážu vyriešiť. A to konkrétne funkcia ROW_NUMBER spolu s PARTITION BY.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;WITH IndexedPhoneNumbers (ContactId, Number, RowIndex) AS&lt;/p&gt;    &lt;p&gt;(&lt;/p&gt;    &lt;p&gt;SELECT ContactId, Number,&lt;/p&gt;    &lt;p&gt;ROW_NUMBER() OVER (PARTITION BY ContactId ORDER BY PhoneNumberId) AS RowIndex&lt;/p&gt;    &lt;p&gt;FROM PhoneNumber&lt;/p&gt;    &lt;p&gt;)&lt;/p&gt;    &lt;p&gt;SELECT C.*, IPN.Number&lt;/p&gt;    &lt;p&gt;FROM Contact C LEFT JOIN&lt;/p&gt;    &lt;p&gt;IndexedPhoneNumbers IPN ON IPN.ContactId = C.ContactId AND IPN.RowIndex = 1&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Možno to niekomu pomôže. Možno niekto pozná ešte elegantnejšie riešenie, tak nech ho kľudne pridá do komentárov.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=128315" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Windows 7 sa začne predávať 22. októbra</title><link>http://blog.aspnet.sk/duracellko/archive/2009/06/03/windows-7-sa-za-ne-pred-225-va-22-okt-243-bra.aspx</link><pubDate>Wed, 03 Jun 2009 07:01:55 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:119604</guid><dc:creator>duracellko</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=119604</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2009/06/03/windows-7-sa-za-ne-pred-225-va-22-okt-243-bra.aspx#comments</comments><description>&lt;p&gt;Táto informácia sama o sebe asi nemá takú vážnosť, aby sa dostala na môj blog. Ale tento krát sa Microsoft trafil do mojich narodenín. Ešte šťastie, že na RC sú celkom dobré ohlasy. Nerád by som bol, keby to bol nejaký nepodarok :)&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=119604" width="1" height="1"&gt;</description></item><item><title>LINQ 2 SQL, DataLoadOptions a CompiledQuery</title><link>http://blog.aspnet.sk/duracellko/archive/2009/04/01/linq-2-sql-dataloadoptions-a-compiledquery.aspx</link><pubDate>Wed, 01 Apr 2009 14:15:28 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:96204</guid><dc:creator>duracellko</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=96204</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2009/04/01/linq-2-sql-dataloadoptions-a-compiledquery.aspx#comments</comments><description>&lt;p&gt;Len pre obnovenie pamäte DataLoadOptions je trieda, kde sa definuje eager-loading pre LINQ 2 SQL. Použitie je asi nasledovné:&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;var context = new MyDataContext(connectionString);&lt;/p&gt;    &lt;p&gt;var dlo = new DataLoadOptions();&lt;/p&gt;    &lt;p&gt;dlo.LoadWith&amp;lt;User&amp;gt;(u =&amp;gt; u.Roles);&lt;/p&gt;    &lt;p&gt;context.LoadOptions = dlo;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;DataLoadOptions má však niekoľko obmedzení.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;LoadOptions sa musí nastaviť ešte pred prvým query. &lt;/li&gt;    &lt;li&gt;LoadOptions, ani samotný DataLoadOptions objekt sa už nemôžu meniť po spustení prvého query. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Vzhľadom na tieto obmedzenia som nastavovanie LoadOptions dal priamo do konštruktoru triedy MyDataContext. Tu som nastavil eager-loading, ktorý je tipický pre celú aplikáciu. Napríklad pre niektoré entity sa načíta rovno aj ich vlastník a podobne.&lt;/p&gt;  &lt;p&gt;Dnes sme riešili performance a niektoré query sa museli predkompilovať.V LINQ 2 SQL na toto slúži trieda CompiledQuery. Použitie je celkom jednoduché:&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;Func&amp;lt;MyDataContext, int, User&amp;gt; getUser;&lt;/p&gt;    &lt;p&gt;getUser = CompiedQuery.Compile((MyDataContext context, int userId) =&amp;gt; context.Users.FirstOrDefault(u =&amp;gt; u.Id == userId));&lt;/p&gt;    &lt;p&gt;var context = new MyDataContext(connectionString);&lt;/p&gt;    &lt;p&gt;User user1 = getUser(context, 1);&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;volanie funkcie getUser trva asi 10tinu času neskompilovaného query.&lt;/p&gt;  &lt;p&gt;Lenže tu sme narazili na problém, že pri volaní getUser nad rôznymi inštanciami MyDataContext to hádzalo výnimku &lt;em&gt;“Compiled queries across DataContexts with different LoadOptions not supported.”&lt;/em&gt; Z tohoto sú jasné obmedzenia vlastnosti LoadOptions, pretože každá expression sa interne skompiluje.&lt;/p&gt;  &lt;p&gt;Naštastie riešenie bolo jednoduché. V statickom konštruktore sa vytvorí jedna inštancia DataLoadOptions a v konštruktore MyDataContext sa do LoadOptions nastaví práve táto jedna inštancia. Keďže sa DataLoadOptions už potom nemení, tak by to malo byť aj thread-safe.&lt;/p&gt;  &lt;p&gt;Čo bolo ale zujímavé, že pri tejto implementácii sa čas kompilácie query (myslím bez použitia CompiledQuery) skrátil asi na polovicu.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=96204" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/LINQ+2+SQL/default.aspx">LINQ 2 SQL</category></item><item><title>Applications = Code + Markup</title><link>http://blog.aspnet.sk/duracellko/archive/2009/02/05/applications-code-markup.aspx</link><pubDate>Thu, 05 Feb 2009 13:12:46 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:70580</guid><dc:creator>duracellko</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=70580</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2009/02/05/applications-code-markup.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://blog.aspnet.sk/blogs/duracellko/wpf_05189169.png"&gt;&lt;img title="wpf" style="border-right:0px;border-top:0px;display:inline;margin-left:0px;border-left:0px;margin-right:0px;border-bottom:0px;" height="244" alt="wpf" src="http://blog.aspnet.sk/blogs/duracellko/wpf_thumb_127EA46F.png" width="201" align="right" border="0" /&gt;&lt;/a&gt; Konečne mi dorazila knižka na tému WPF od legendy &lt;a href="http://www.charlespetzold.com"&gt;Charles Petzold&lt;/a&gt;. Charles Petzold je expert na vývoj užívateľského rozhrania pod Windows. Čítal som od neho ešte knižku &lt;a href="http://www.microsoft.com/learning/en/us/Books/2344.aspx"&gt;Programming Windows&lt;/a&gt;, kde písal o programovaní pod Windows 3.1 v C pomocou WinAPI. To bolo ešte za čias, keď sa ani ináč nedalo, lebo ešte neexistovalo ani MFC ani iné objektové knižnice na WinAPI. Síce som nikdy nenapísal žiadnu Windows aplikáciu v čistom C, ale aspoň som pochopil architektúru Windows UI. Teda hlavne ako funguje posielanie správ oknám a podobne. A tažím z toho do teraz. Aj keď používam .NET Windows Forms API, tak si viem predstaviť, čo sa deje na pozadí.&lt;/p&gt;  &lt;p&gt;Keďže WPF je úplne nová architektúra (aspoň tak som to zatiaľ pochopil) a nie len nové objektové rozhranie nad WinAPI, tak som sa rozhodol, že znova siahnem po knižke od svojej legendy, aby mi odhalil túto novú architektúru. Síce WPF už existuje nejaký čas, ale ja som sa k tomu dostal až teraz. Ale veď nikdy nie je neskoro.&lt;/p&gt;  &lt;p&gt;Viac info o knižke nájdete na &lt;a title="http://www.microsoft.com/learning/en/us/Books/6476.aspx" href="http://www.microsoft.com/learning/en/us/Books/6476.aspx"&gt;http://www.microsoft.com/learning/en/us/Books/6476.aspx&lt;/a&gt;&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=70580" width="1" height="1"&gt;</description></item><item><title>Anonymní delegáti vo foreach</title><link>http://blog.aspnet.sk/duracellko/archive/2008/10/22/anonymn-237-deleg-225-ti-vo-foreach.aspx</link><pubDate>Wed, 22 Oct 2008 11:32:35 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:48193</guid><dc:creator>duracellko</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=48193</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2008/10/22/anonymn-237-deleg-225-ti-vo-foreach.aspx#comments</comments><description>&lt;p&gt;Dnes to bud&amp;#250; 2 tipy v jednom čl&amp;#225;nku. Prv&amp;#253; probl&amp;#233;m je, ako nač&amp;#237;tať v LINQ 2 SQL asociovan&amp;#233; kolekcie. M&amp;#225;m entity &lt;strong&gt;Customer&lt;/strong&gt; a &lt;strong&gt;Contact&lt;/strong&gt;. A samozrejme Customer m&amp;#225; kolekciu &lt;strong&gt;Contacts&lt;/strong&gt;. A potrebujem v jednej met&amp;#243;de nač&amp;#237;tať z&amp;#225;kazn&amp;#237;kov aj s ich kontaktmi. D&amp;#225; sa na to použiť trieda DataLoadOptions. Asi nasledovne:&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;var dlo = new DataLoadOptions();&lt;/p&gt;    &lt;p&gt;dlo.LoadWith&amp;lt;Customer&amp;gt;(c =&amp;gt; c.Contacts);&lt;/p&gt;    &lt;p&gt;dataContext.LoadOptions = dlo;&lt;/p&gt;    &lt;p&gt;return dataContext.Customers.ToList();&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Toto zabezpeč&amp;#237;, že v jednom SQL pr&amp;#237;kaze sa nač&amp;#237;taj&amp;#250; z&amp;#225;kazn&amp;#237;ci aj ich kontakty. Čiže iba jeden dotaz na datab&amp;#225;zu, čo je oveľa efekt&amp;#237;vnej&amp;#353;ie ako keby sa pre každ&amp;#233;ho z&amp;#225;kazn&amp;#237;ka nahr&amp;#225;vali kontakty pomocou lazy-load met&amp;#243;dy. Probl&amp;#233;m je ale v tom, že kontakty nepotrebujem nač&amp;#237;tať vždy, ale len v určitej met&amp;#243;de. A vlastnosť LoadOptions m&amp;#225; nasledovn&amp;#233; obmedzenia:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Ak objekt DataLoadOptions prirad&amp;#237;m vlastnosti LoadOptions, tak tento objekt nem&amp;#244;žem meniť. To znamen&amp;#225;, že nem&amp;#244;žem zavolať met&amp;#243;du LoadWith. &lt;/li&gt;    &lt;li&gt;Ak sa na danom DataContext objekte spustilo nejak&amp;#233; query, tak vlastnosť LoadOptions nie je možn&amp;#233; zmeniť. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Na&amp;#353;ťastie kolekcia Contacts m&amp;#225; met&amp;#243;du SetSource, čiže kontakty pre z&amp;#225;kazn&amp;#237;ka m&amp;#244;žem nač&amp;#237;tať z ľubovoľn&amp;#233;ho zdroja typu IEnumerable&amp;lt;Contact&amp;gt;. Takže najprv nač&amp;#237;tam z&amp;#225;kazn&amp;#237;kov. Potom nač&amp;#237;tam v&amp;#353;etky kontakty t&amp;#253;chto z&amp;#225;kazn&amp;#237;kov do kolekcie List&amp;lt;Contact&amp;gt;. S&amp;#250; to s&amp;#237;ce 2 dotazy na datab&amp;#225;zu namiesto jedn&amp;#233;ho, ale st&amp;#225;le je to kon&amp;#353;tantn&amp;#253; počet oproti line&amp;#225;rnemu pri lazy-load. No a potom pre každ&amp;#233;ho z&amp;#225;kazn&amp;#237;ka stač&amp;#237; nastaviť zdroj kontaktov nie z datab&amp;#225;zy, ale z tohto listu.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;/// &amp;lt;summary&amp;gt;&lt;/p&gt;    &lt;p&gt;/// Loads the contacts for customers in one SQL statement.&lt;/p&gt;    &lt;p&gt;/// &amp;lt;/summary&amp;gt;&lt;/p&gt;    &lt;p&gt;/// &amp;lt;param name=&amp;quot;customers&amp;quot;&amp;gt;The customers to load contacts for.&amp;lt;/param&amp;gt;&lt;/p&gt;    &lt;p&gt;/// &amp;lt;param name=&amp;quot;customerQuery&amp;quot;&amp;gt;The customer query. If null, then customers are selected from the list.&amp;lt;/param&amp;gt;&lt;/p&gt;    &lt;p&gt;public void LoadCustomerContacts(IList&amp;lt;Customer&amp;gt; customers, IQueryable&amp;lt;Customer&amp;gt; customerQuery)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;if (customers == null)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;throw new ArgumentNullException(&amp;quot;customers&amp;quot;);&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;IQueryable&amp;lt;Contact&amp;gt; contactsQuery = null;&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;if (customerQuery != null)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;contactsQuery = Context.Contacts.Where(c =&amp;gt; customerQuery.Any(cus =&amp;gt; cus == c.Customer));&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;else&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;int[] customerIds = customers.Select(c =&amp;gt; c.Id).ToArray();&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;contactsQuery = Context.Contacts.Where(c =&amp;gt; customerIds.Contains(c.CustomerId));&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;var contacts = contactsQuery.ToList();&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;foreach (var customer in customers)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;if (!customer.Contacts.HasLoadedOrAssignedValues)&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:66px;"&gt;customer.Contacts.SetSource(contacts.Where(c =&amp;gt; c.CustomerId == customer.Id));&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;}&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;A tu som narazil na probl&amp;#233;m s anonymn&amp;#253;m deleg&amp;#225;tom alebo lambda funkciou vo foreach cykle. Teda sa dost&amp;#225;vam k druh&amp;#233;mu bodu v tomto čl&amp;#225;nku. Keď som t&amp;#250;to met&amp;#243;du spustil, tak v&amp;#353;etci z&amp;#225;kazn&amp;#237;ci mali rovnak&amp;#250; množinu kontaktov a to boli kontakty posledn&amp;#233;ho z&amp;#225;kazn&amp;#237;ka. S&amp;#237;ce som hneď pochopil, v čom je probl&amp;#233;m, ale aby som ho mohol vysvetliť, tak najprv vysvetl&amp;#237;m ako funguj&amp;#250; anonymn&amp;#237; deleg&amp;#225;ti. Lambda funkcia je len in&amp;#253; z&amp;#225;pis anonymn&amp;#233;ho deleg&amp;#225;ta, takže pre ňu to plat&amp;#237; rovnako.&lt;/p&gt;  &lt;p&gt;Predch&amp;#225;dzaj&amp;#250;ca funkcia sa d&amp;#225; zap&amp;#237;sať a prelož&amp;#237; sa nasledovne. Najprv sa vygeneruje pomocn&amp;#225; trieda, ktor&amp;#225; udržuje stav.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;private class DelegateClass&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;public Customer customer;&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;&amp;#160;&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;public bool DelegateMethod(Contact c)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;return c.CustomerId == customer.Id;&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Potom sa foreach cyklus prelož&amp;#237; nasledovne.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;DelegateClass delegateStatus = new DelegateClass();&lt;/p&gt;    &lt;p&gt;IEnumerator&amp;lt;Customer&amp;gt; enumerator = customers.GetEnumerator();&lt;/p&gt;    &lt;p&gt;enumerator.Reset();&lt;/p&gt;    &lt;p&gt;while (enumerator.MoveNext())&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;delegateStatus.customer = enumerator.Current;&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;if (!delegateStatus.customer.Contacts.HasLoadedOrAssignedValues)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;delegateStatus.Contacts.SetSource(contacts.Where(delegateStatus.DelegateMethod));&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Samozrejme, že tento m&amp;#244;j preklad je len približn&amp;#253; a hlavne som si vymyslel rozumnej&amp;#353;ie n&amp;#225;zvy ako tie, čo generuje C# kompil&amp;#225;tor. Ale d&amp;#244;ležit&amp;#233; je, že objekt typu DelegateClass sa vytv&amp;#225;ra iba raz pred vykonan&amp;#237;m cyklu. Takže na konci maj&amp;#250; v&amp;#353;etky zdroje kontaktov v podmienke Where odkaz na ten ist&amp;#253; objekt DelegateClass a teda toho ist&amp;#233;ho z&amp;#225;kazn&amp;#237;ka. A preto sa vždy nač&amp;#237;taj&amp;#250; len kontakty posledn&amp;#233;ho z&amp;#225;kazn&amp;#237;ka. Rie&amp;#353;en&amp;#237;m je samozrejme presun&amp;#250;ť riadok &amp;quot;DelegateClass delegateStatus = new DelegateClass()&amp;quot; do vn&amp;#250;tra cyklu. Takže stačilo prep&amp;#237;sať foreach cyklus nasledovne.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;foreach (var customer in customers)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;if (!customer.Contacts.HasLoadedOrAssignedValues)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;int customerId = customer.Id;&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;customer.Contacts.SetSource(contacts.Where(c =&amp;gt; c.CustomerId == customerId));&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Alebo druh&amp;#225; možnosť je hneď za SetSource nahrať kolekciu kontaktov.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;foreach (var customer in customers)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;if (!customer.Contacts.HasLoadedOrAssignedValues)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;customer.Contacts.SetSource(contacts.Where(c =&amp;gt; c.CustomerId == customer.Id));&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;customer.Contacts.Load();&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Z&amp;#225;ver je jednoduch&amp;#253;. Pri použit&amp;#237; anonymn&amp;#253;ch deleg&amp;#225;tov v cykle si treba vždy uvedomiť, kde sa vytv&amp;#225;ra in&amp;#353;tancia stavov&amp;#233;ho objektu deleg&amp;#225;ta. Aby sa nestalo, že r&amp;#244;zni deleg&amp;#225;ti zdieľaj&amp;#250; ten ist&amp;#253; stav.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=48193" width="1" height="1"&gt;</description></item><item><title>Forms authentication na Reporting Services</title><link>http://blog.aspnet.sk/duracellko/archive/2008/10/10/forms-authentication-na-reporting-services.aspx</link><pubDate>Fri, 10 Oct 2008 11:45:20 GMT</pubDate><guid isPermaLink="false">cbdfeddd-8b45-43cb-b10b-361e40cba84b:47565</guid><dc:creator>duracellko</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.aspnet.sk/duracellko/rsscomments.aspx?PostID=47565</wfw:commentRss><comments>http://blog.aspnet.sk/duracellko/archive/2008/10/10/forms-authentication-na-reporting-services.aspx#comments</comments><description>&lt;p&gt;M&amp;#225;m trochu času, tak sa m&amp;#244;žete te&amp;#353;iť z toho, že oživ&amp;#237;m trochu svoj .NET blog. Tento kr&amp;#225;t nap&amp;#237;&amp;#353;em ako som rozbeh&amp;#225;val ASP.NET forms authentication na Reporting Services. Toto som s&amp;#237;ce rie&amp;#353;il d&amp;#225;vnej&amp;#353;ie, ale až teraz som si na&amp;#353;iel čas to nap&amp;#237;sať.&lt;/p&gt;  &lt;p&gt;Asi e&amp;#353;te nie som dostatočne google addicted, ale najprv som siahol po &lt;a href="http://msdn.microsoft.com"&gt;MSDN&lt;/a&gt; a až potom po google. Na MSDN s&amp;#237;ce bolo nap&amp;#237;san&amp;#233;, ktor&amp;#233; interfacy m&amp;#225;m implementovať, ale len veľmi stručne tam bolo nap&amp;#237;san&amp;#233; že ako ich m&amp;#225;m implementovať. Teda o niektor&amp;#253;ch oper&amp;#225;ci&amp;#225;ch interfacov som sa viac dozvedel z ich n&amp;#225;zvu ako zo samotn&amp;#233;ho popisu v MSDN. Takže som pre&amp;#353;iel na možnosť B, a teda google. Najlep&amp;#353;ie by bolo n&amp;#225;jsť čl&amp;#225;nok o tom, ako to už niekto urobil. A aj som na&amp;#353;iel. MS na &lt;a href="http://www.codeplex.com/"&gt;codeplexe&lt;/a&gt; zverejňuje v&amp;#353;etky ofici&amp;#225;lne sample k SQL Server. Čiže je tam možn&amp;#233; stiahnuť aj pr&amp;#237;kladov&amp;#250; datab&amp;#225;zu AdventureWorks, ktor&amp;#225; bola dod&amp;#225;van&amp;#225; s SQL Server 2005. No a na&amp;#353;iel som tam aj sadu pr&amp;#237;kladov pre Reporting Services a v tejto sade pr&amp;#237;kladov je aj pr&amp;#237;klad na forms authentication. V&amp;#353;etko je to na str&amp;#225;nke &lt;a title="http://www.codeplex.com/MSFTRSProdSamples/" href="http://www.codeplex.com/MSFTRSProdSamples/"&gt;http://www.codeplex.com/MSFTRSProdSamples/&lt;/a&gt; a pr&amp;#237;klad sa vol&amp;#225; &lt;strong&gt;Security Extension Sample&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Takže som si dan&amp;#253; pr&amp;#237;klad stiahol, otvoril a spravil svoju vlastn&amp;#250; implement&amp;#225;ciu. Tu som si v&amp;#353;imol, že kusy k&amp;#243;du, ktor&amp;#233; boli uveden&amp;#233; v MSDN ako pr&amp;#237;klad, s&amp;#250; vlastne z tohto pr&amp;#237;kladu. V&amp;#228;č&amp;#353;ina pr&amp;#225;ce spoč&amp;#237;vala v copy&amp;amp;paste. Zmenil som len to, že som použil vlastn&amp;#253; membership provider a pri autoriz&amp;#225;cii je možn&amp;#233; v ACL použiť aj rolu, nie len už&amp;#237;vateľa. Nasadil som to na Report Server a ono to norm&amp;#225;lne fungovalo. Ale žiaľ nie až tak norm&amp;#225;lne. Probl&amp;#233;m bol v tom, že ak som zadal do prehliadača adresu Report Serveru, tak zobrazenie login str&amp;#225;nky trvalo asi 1 min&amp;#250;tu. Potom, keď sa už&amp;#237;vateľ prihl&amp;#225;sil, tak v&amp;#353;etko fungovalo tak ako m&amp;#225;. Fungovalo nastavovanie pr&amp;#225;v a bolo to rychle ako Report Server, ktor&amp;#253; použ&amp;#237;va windows autentifik&amp;#225;ciu.&lt;/p&gt;  &lt;p&gt;Pozrel som log Report Server a tam boli NullReferenceException. Čo e&amp;#353;te nie je d&amp;#244;vod min&amp;#250;tov&amp;#233; zdržanie. Potom som pozrel Report Web (teda front-end) log a tam boli time-outy. Tak som zase otvoril svoj obľ&amp;#250;ben&amp;#253; &lt;a href="http://www.red-gate.com/products/reflector/"&gt;.NET Reflector&lt;/a&gt; a na&amp;#353;iel som si funkcie, ktor&amp;#233; boli uveden&amp;#233; v stacku pri v&amp;#253;nimk&amp;#225;ch. A problematick&amp;#225; proced&amp;#250;ra bola nasledovn&amp;#225;. Najprv e&amp;#353;te uvediem implement&amp;#225;ciu GetUserInfo oper&amp;#225;cie v IAuthenticationExtension, ktor&amp;#225; bola použit&amp;#225; v pr&amp;#237;klade.&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;// If the current user identity is not null,&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;// set the userIdentity parameter to that of the current user&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;if (HttpContext.Current != null &amp;amp;&amp;amp; HttpContext.Current.User != null)&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;{&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;userIdentity = HttpContext.Current.User.Identity;&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;}&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;else&lt;/p&gt;    &lt;p style="margin-left:44px;"&gt;userIdentity = null;&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;// initialize a pointer to the current user id to zero&lt;/p&gt;    &lt;p style="margin-left:22px;"&gt;userId = IntPtr.Zero;&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;ol&gt;   &lt;li&gt;Už&amp;#237;vateľ zobraz&amp;#237; Default.aspx str&amp;#225;nku.&lt;/li&gt;    &lt;li&gt;Každ&amp;#225; str&amp;#225;nka v RS front-ende je odvoden&amp;#225; od triedy ReportingPage. Na tejto str&amp;#225;nke sa odchyt&amp;#237; udalosť Init.&lt;/li&gt;    &lt;li&gt;V tejto udalosti sa zisťuje, či sa m&amp;#225; pre komunik&amp;#225;ciu s back-endom použiť SSL alebo nie. &lt;/li&gt;    &lt;li&gt;Najprv sa zavol&amp;#225; ListSecureMethods() web met&amp;#243;da na back-ende bez použitia SSL. V konfigur&amp;#225;cii som nezapol, že SSL je vyn&amp;#250;ten&amp;#233;.&lt;/li&gt;    &lt;li&gt;Na back-ende sa odchyt&amp;#237; udalosť HttpApplication.AuthenticateRequest.&lt;/li&gt;    &lt;li&gt;V tejto udalosti sa zist&amp;#237;, že sa použ&amp;#237;va forms authentication a uživateľ nie je prihl&amp;#225;sen&amp;#253; (HttpContext.Current.User == null), tak sa do response headers prid&amp;#225; položka &lt;em&gt;RSNotAuthenticated&lt;/em&gt;.&lt;/li&gt;    &lt;li&gt;Ďalej sa v tejto udalosti zavol&amp;#225; GetUserInfo met&amp;#243;da na&amp;#353;ej authentication extension. Už&amp;#237;vateľ e&amp;#353;te nie je prihl&amp;#225;sen&amp;#253;, takže ako userIdentity vr&amp;#225;ti null. Lenže ďalej sa vol&amp;#225; IIdentity.Name, čo vyvol&amp;#225; NullReferenceException, ktor&amp;#250; som na&amp;#353;iel v logu.&lt;/li&gt;    &lt;li&gt;T&amp;#225;to v&amp;#253;nimka sa po&amp;#353;le na front-end. Pri prij&amp;#237;man&amp;#237; odpovede z back-endu sa n&amp;#225;jde v hlavičk&amp;#225;ch položka &lt;em&gt;RSNotAuthenticated&lt;/em&gt;, takže sa do response headers, ktor&amp;#233; p&amp;#244;jdu z front-endu na prehliadač, zap&amp;#237;&amp;#353;e, že sa m&amp;#225; presmerovať na login page. Ale neukonč&amp;#237; sa spracovanie requestu.&lt;/li&gt;    &lt;li&gt;Doteraz by v&amp;#353;etko ako-tak fungovalo, až na to zapisovanie NullReferenceException do logu. T&amp;#225;to v&amp;#253;nimka sa odchyt&amp;#237; na front-ende. Ten si mysl&amp;#237;, že back-end nekomunikuje na nezabezpečenej linke, tak sk&amp;#250;si zavolať ListSecureMethods() web met&amp;#243;du cez SSL.&lt;/li&gt;    &lt;li&gt;30 sek&amp;#250;nd sa čak&amp;#225;.&lt;/li&gt;    &lt;li&gt;Potom sa hod&amp;#237; WebException s t&amp;#253;m, že nastal time out. Toto sa tiež zap&amp;#237;salo do logu. &lt;/li&gt;    &lt;li&gt;T&amp;#225;to v&amp;#253;nimka sa odchytila v HttpApplication.Error, kde sa spust&amp;#237; HttpServerUtility.Transfer s t&amp;#253;m, že sa spust&amp;#237; Error.aspx. Samozrejme, že aj t&amp;#225;to str&amp;#225;nka je odvoden&amp;#225; od ReportingPage, takže cel&amp;#253; cirkus od bodu 2 sa zopakuje. Čo je ďal&amp;#353;&amp;#237;ch 30 sek&amp;#250;nd čakania.&lt;/li&gt;    &lt;li&gt;Nakoniec sa na klienta po&amp;#353;le asi str&amp;#225;nka, že nastala neočak&amp;#225;van&amp;#225; chyba. Lenže t&amp;#225;to sa ani nezobraz&amp;#237;, pretože browser si hneď v hlavičke preč&amp;#237;ta, že sa m&amp;#225; presmerovať na Login.aspx.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Najprv som si myslel, že sa probl&amp;#233;m vyrie&amp;#353;i, keď sa na web server nain&amp;#353;taluje SSL certifik&amp;#225;t. Lenže toto nepomohlo. Možno to nebolo &amp;#250;plne spr&amp;#225;vne nain&amp;#353;talovan&amp;#233;, lebo ten certifik&amp;#225;t samozrejme nebol overen&amp;#253; certifikačnou autoritou. Tak som sa rozhodol, že met&amp;#243;du GetUserInfo z pr&amp;#237;kladu mierne uprav&amp;#237;m. A to nasledovne:&lt;/p&gt;  &lt;div class="code"&gt;   &lt;p&gt;public const string GuestUserName = &amp;quot;_Guest_&amp;quot;;&lt;/p&gt;    &lt;p&gt;public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)&lt;/p&gt;    &lt;p&gt;{&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; if (HttpContext.Current != null &amp;amp;&amp;amp; HttpContext.Current.User != null)&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; userIdentity = HttpContext.Current.User.Identity;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; else&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; userIdentity = new GenericIdentity(GuestUserName);&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; userId = IntPtr.Zero;&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Potom e&amp;#353;te samozrejme bolo potrebn&amp;#233; upraviť AuthorizationExtension tak, že už&amp;#237;vateľ _Guest_ m&amp;#225; v&amp;#353;etko zak&amp;#225;zan&amp;#233; bez ohľadu na to, čo je v ACL zoznamoch. A min&amp;#250;tov&amp;#233; čakanie zmizlo :)&lt;/p&gt;  &lt;p&gt;Takže ak aj vy budete siahať po pr&amp;#237;klade na security extension pre Reporting Services, tak si dajte pozor na t&amp;#250;to chybu.&lt;/p&gt;  &lt;p&gt;Ďal&amp;#353;&amp;#237; probl&amp;#233;m sa vyskytol, keď som na Report Server chcel pristupovať cez SQL Server Management Studio, tak mi st&amp;#225;le tvrdil, že som nezadal spr&amp;#225;vne meno alebo heslo. Probl&amp;#233;m bol v tom, že v na&amp;#353;ej aplik&amp;#225;cii s&amp;#250; uživeteľsk&amp;#233; men&amp;#225; v tvare &lt;em&gt;domain\username&lt;/em&gt;. Samozrejme, že domain nie je NT dom&amp;#233;na, ale jednoducho už&amp;#237;vateľsk&amp;#233; meno sa sklad&amp;#225; z dvoch čast&amp;#237; oddelen&amp;#253;ch opačn&amp;#253;m lom&amp;#237;tkom. Lenže SQL Server Management Studio t&amp;#250; časť pred lom&amp;#237;tkom zahod&amp;#237;. Teda možno to d&amp;#225;va do parametru domain pri prihlasovan&amp;#237;, ale ten sa pri forms authentication ignoruje. Takže som to vyrie&amp;#353;il tak, že moja security extension pracuje s menami v tvare &lt;em&gt;domain/username&lt;/em&gt;. Čiže použ&amp;#237;vam norm&amp;#225;lne lom&amp;#237;tko. A vždy pri použit&amp;#237; membership providera zamen&amp;#237;m norm&amp;#225;lne lom&amp;#237;tko za opačn&amp;#233;.&lt;/p&gt;
		&lt;script src="http://connect.facebook.net/en_US/all.js#xfbml=1"&gt;&lt;/script&gt;&lt;fb:like href="" show_faces="true" width="450" font=""&gt;&lt;/fb:like&gt;&lt;img src="http://blog.aspnet.sk/aggbug.aspx?PostID=47565" width="1" height="1"&gt;</description><category domain="http://blog.aspnet.sk/duracellko/archive/tags/Reporting+Services/default.aspx">Reporting Services</category></item></channel></rss>