<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;DEIFR3c6cCp7ImA9WhRUFkg.&quot;"><id>tag:blogger.com,1999:blog-17332816</id><updated>2012-01-27T17:28:36.918+08:00</updated><category term="Rx" /><category term=".Net 2.0" /><category term="java" /><category term="Powershell" /><category term="Kinect" /><category term="debugging" /><category term="VisualStudio" /><category term="security" /><category term="TFS" /><category term="Deployment" /><category term="Async" /><category term="SharePoint" /><category term="PerformancePoint" /><category term="CI" /><category term="Build" /><category term=".Net 4" /><category term="Oracle" /><category term="IIS" /><category term="TechEd" /><category term="C#" /><category term="Touch" /><category term="MSDN" /><category term="CCNet" /><category term="BAT" /><category term="PSake" /><category term="Code Review" /><category term="Win8" /><category term="sql" /><category term="WCF" /><category term="WiX" /><category term="PowerDbg" /><category term="SSAS" /><category term="SSRS" /><category term="log4net" /><category term=".net" /><category term="VB.Net" /><category term="ASP.Net" /><category term="JavaScript" /><category term="NAnt" /><category term="SSIS" /><category term="WinForms" /><category term="WPF" /><category term="Dynamics CRM" /><category term="MDX" /><category term="resharper" /><category term="Silverlight" /><title>Cup(Of T)</title><subtitle type="html">.net dregs from my mental teacup</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>198</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/CupofT" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="cupoft" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0YMSHgycCp7ImA9WhRSF0Q.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-144968445423318997</id><published>2011-11-20T22:26:00.001+08:00</published><updated>2011-11-20T22:26:29.698+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-20T22:26:29.698+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Kinect" /><title>Gotchas with the Kinect SDK for Windows</title><content type="html">&lt;p&gt;Playing with the Kinect SDK for Windows, and having a ball, but the doco is (understandably) a bit rubbish in places, or to be more specific – lacks critical details around the form that a parameter takes, where that detail is important.&lt;/p&gt;  &lt;p&gt;Anyway, this is my list of gotchas so far:&lt;/p&gt;  &lt;h4&gt;Depth Data Inverted when Player Index tracking enabled&lt;/h4&gt;  &lt;p&gt;Bizarrely, whether you initialize and open your depth image stream with ImageType.Depth or ImageType.DepthAndPlayerIndex makes the difference between whether what you get is ‘right way round’ or horizontally inverted.&lt;/p&gt;  &lt;p&gt;Inverted is generally more useful, because it matches with the ‘mirror image’ video stream. So why isn’t the stream like that always? Seems like an unnecessary inconsistency to me, and one you might want to &lt;em&gt;spell out in the doco&lt;/em&gt;.&lt;/p&gt;  &lt;h4&gt;Different Depth Data Pixel Values when Player Index Tracking Enabled&lt;/h4&gt;  &lt;p&gt;When you do turn player index tracking on, the depth stream ‘pixels’ are lshifted 3 positions, leaving the lower 3 bits for the player index. This &lt;em&gt;is&lt;/em&gt; documented, and I understand you’ve got to put the player index somewhere, but why not make the format consistent in both cases, and just leave the lower bits zero if tracking not enabled? Better still, why not put the (optional) player index in the high bits?&lt;/p&gt;  &lt;p&gt;This is especially irritating because...&lt;/p&gt;  &lt;h4&gt;GetColorPixelCoordinatesFromDepthPixel() Requires Bit-Shifted Input&lt;/h4&gt;  &lt;p&gt;The nuiCamera.GetColorPixelCoordinatesFromDepthPixel() mapping method expects the ‘depthValue’ parameter to be in the format it &lt;em&gt;would have been&lt;/em&gt; if you had player tracking enabled. If you don’t, you’ll have to lshift 3 places to the left yourself, just to make it work. So depending on how you setup the runtime, the pixels from one part of the API can or can’t be passed to another part of the API. That’s poor form, if you ask me.&lt;/p&gt;  &lt;p&gt;Not that you’ll find that in the doco of course, least of all the parameter doco.&lt;/p&gt;  &lt;h4&gt;No GetDepthPixelFromColorPixelCoordinates Method&lt;/h4&gt;  &lt;p&gt;Ok, so I &lt;em&gt;understand&lt;/em&gt; that the depth to video coordinate space translation is a lossy one, but I still don’t see why this method doesn’t exist.&lt;/p&gt;  &lt;p&gt;I picked up the Kinect SDK and the first thing I wanted to do was depth-clipping background removal. And the easy way to do this is to loop through the &lt;em&gt;video &lt;/em&gt;pixels, and for each find the corresponding &lt;em&gt;depth pixel &lt;/em&gt;and see what its depth was. And you can’t do that. &lt;/p&gt;  &lt;p&gt;Instead you have to loop through the &lt;em&gt;depth&lt;/em&gt; pixels and call the API method to translate to video pixels, but because there are less of them compared to the video pixels, you have to paint them out as a 2x2 block, and even then there’ll be lots of video pixels you don’t processes, so many you have to run the loop twice: once to set all the video pixels to some kind of default state, and once for those that map to depth pixels to put the depth ‘on’.&lt;/p&gt;  &lt;p&gt;Just didn’t feel right.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-144968445423318997?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/zgjDErqcehI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/144968445423318997/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=144968445423318997" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/144968445423318997?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/144968445423318997?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/11/playing-with-kinect-sdk-for-windows-and.html" title="Gotchas with the Kinect SDK for Windows" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;CEUMQ3g6eyp7ImA9WhdVF00.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-3192528612061658209</id><published>2011-09-22T20:51:00.005+08:00</published><updated>2011-09-22T22:38:02.613+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-22T22:38:02.613+08:00</app:edited><title>Geolocation in HTML 5</title><content type="html">Ok, so it’s not actually part of HTML 5 (the spec), but conceptually at least it’s definitely part of HTML 5 (the brand).&lt;br /&gt;
&lt;br /&gt;
So what’s actually involved. Hmm. OH MY GOD IS IT THAT EASY !?&lt;br /&gt;
&lt;code&gt;   function showMap(position) {&lt;br /&gt;
// Show a map centered at (position.coords.latitude, position.coords.longitude).&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// One-shot position request.&lt;br /&gt;
navigator.geolocation.getCurrentPosition(showMap);&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
[from the &lt;a href="http://dev.w3.org/geo/api/spec-source.html"&gt;W3 geolocation spec&lt;/a&gt;]&lt;br /&gt;
&lt;br /&gt;
So you just rock up to &lt;a href="http://html5demos.com/geo" title="http://html5demos.com/geo"&gt;html5demos.com/geo&lt;/a&gt; and ...&lt;br /&gt;
&lt;a href="http://lh3.ggpht.com/-LUOQVJTI8eU/TnsvNPHHbCI/AAAAAAAAANM/o8QAvZOOLrg/s1600-h/image%25255B3%25255D.png"&gt;&lt;img alt="image" border="0" height="68" src="http://lh5.ggpht.com/-yeSzqhOIzHw/TnsvN5nyMMI/AAAAAAAAANQ/nuqtbYuOcjw/image_thumb%25255B1%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="570" /&gt;&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
Holy crap. I won’t show you the resulting map because it shows where I live. What’s really freaky about that is &lt;strong&gt;this netbook doesn’t have a GPS. &lt;/strong&gt;So either Windows 7 or IE 9 has fallen back to IP-based location inference, and somehow still got me &lt;em&gt;only one house out&lt;/em&gt;.&lt;br /&gt;
&lt;br /&gt;
I’m totally freaked out.&lt;br /&gt;
&lt;br /&gt;
Anyway, the point of all this is that IE 9 is the browser for Windows Phone 7.5 (Mango), which – if it actually supports this API (and Wikipedia says &lt;a href="http://en.wikipedia.org/wiki/Windows_Phone_7.5#Internet_Explorer_9_Mobile"&gt;yes it does&lt;/a&gt;) - means you can write location-aware mobile apps targeting Mango without having to ‘go native’. And for the demo I want to put together, this can only be a good thing...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-3192528612061658209?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/2p4h3iKlWTU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/3192528612061658209/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=3192528612061658209" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3192528612061658209?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3192528612061658209?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/09/geolocation-in-html-5.html" title="Geolocation in HTML 5" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-yeSzqhOIzHw/TnsvN5nyMMI/AAAAAAAAANQ/nuqtbYuOcjw/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0YER3Y8cSp7ImA9WhdVEEg.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-1752329512665753722</id><published>2011-09-15T10:51:00.000+08:00</published><updated>2011-09-15T10:51:46.879+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-15T10:51:46.879+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Win8" /><title>Windows 8: First Impressions</title><content type="html">Q: "Your first impression? Love or hate?"&lt;br /&gt;
&lt;br /&gt;
Well that's a really good question.&lt;br /&gt;
 &lt;br /&gt;
I was always horribly dissapointed with my HP TX2 multitouch laptop, and whislt some of that was about the hardware (rubbish battery life, noisy fan), some of it was just how non-touch capable Windows 7 was to actually use. Windows Media Center achieves many of my 'media center kiosk' wants, but doesn't let me Skype or browse the web without dropping back to the desktop and so forth.  Then you've got to go and find the mouse and all that crap. I realised that, like Media Center, a different usage type required a very different UI experience.&lt;br /&gt;
 &lt;br /&gt;
So in many ways what I was after was absolutely where Windows 8 is going. And (in the 30 mins I've actually played with it) I love it for that.&lt;br /&gt;
 &lt;br /&gt;
That being said, they're going to have to be really careful they don't throw the baby out with the bath water. Ok the desktop's still there for 'traditional' apps, but the Start bar is gone, as is apparently ALT-TAB task switching. And without a touch screen, that metro UI really sucks actually.&lt;br /&gt;
 &lt;br /&gt;
It'd be more than a shame if embracing a device/cloud future required ditching 10 years worth of desktop productivity, it'd be a Vista-scale corporate-desktop disaster.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-1752329512665753722?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/5ADdzZoDSyU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/1752329512665753722/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=1752329512665753722" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1752329512665753722?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1752329512665753722?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/09/windows-8-first-impressions.html" title="Windows 8: First Impressions" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;CEMFQ3c_eCp7ImA9WhdWGUs.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-8801354170141834448</id><published>2011-09-14T09:06:00.000+08:00</published><updated>2011-09-14T09:06:52.940+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-14T09:06:52.940+08:00</app:edited><title>Yes, Silverlight is Dead</title><content type="html">Not exactly &lt;a href="http://www.google.com/search?q=is+silverlight+dead"&gt;quick off the block predicting this&lt;/a&gt;, but I didn't want to rush to judgement. But yes, Silverlight is dead, &lt;a href="http://www.winrumors.com/silverlight-isnt-dead-its-the-heart-of-windows-phone-windows-8-and-xbox/"&gt;on the desktop at least&lt;/a&gt;.[1]&lt;br /&gt;
&lt;br /&gt;
Why? Reach. Silverlight was always going to be playing catchup to Flash, which took pretty much a decade, remember, to get ubiquity. Silverlight just didn't have time on its side. Today if you build an app in Silverlight you can target contemporary browsers on Windows/Mac. By contrast if you build it in HTML you can target Macs, Linux, iPods, iPads, Android, Windows Phone, Kindles, PS3... the list goes on.&lt;br /&gt;
&lt;br /&gt;
To put Silverlight out to all those individual devices is going to take Microsoft a heap of time and effort. By contrast all of those devices have web browsers already, most of them pretty good ones, and getting better all the time.&lt;br /&gt;
&lt;br /&gt;
It's a numbers game. The browsers finally won.&lt;br /&gt;
&lt;br /&gt;
But can HTML realistically replace Silverlight? Absolutely. Not entirely, not today, but surprisingly close, and getting closer by the day. The foundations for mature, maintainable web-client development are finally being put down. And the tooling. Visual Studio 2010's javascript IntelliSense is pretty damn impressive, and already supports jquery for example. Add support for MVVM development (ala knockout.js) and you've got a decent development workflow to rival what you might be used to in WPF/Silverlight/Winforms land (we'll probably see more about this out of &lt;a href="http://www.buildwindows.com/"&gt;Build&lt;/a&gt; this week). And don't forget there's a JS version of RX.&lt;br /&gt;
&lt;br /&gt;
Sure, browser-based javascript is somewhat limited compared to the Silverlight runtime. The touch support isn't quite there yet, for example. But it's more than enough to support UI interaction, and the gap's closing awfully fast.&lt;br /&gt;
&lt;br /&gt;
As a developer who started in web, then moved to the desktop I'm really excited about all of this because I can see a future that finally blends the best of both worlds.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;[1] I'll clarify before I get flamed: Silverlight is not dead &lt;em&gt;today&lt;/em&gt;. I'll be starting a new project using it real soon actually. But the transition is going to be pretty abrupt. I'll be amazed if you start &lt;em&gt;any&lt;/em&gt; new Silverlight projects next year.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-8801354170141834448?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/6cZwP1hOlHA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/8801354170141834448/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=8801354170141834448" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/8801354170141834448?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/8801354170141834448?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/09/yes-silverlight-is-dead.html" title="Yes, Silverlight is Dead" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D04HQHc-cCp7ImA9WhdWE0w.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-156044347681261056</id><published>2011-09-03T09:56:00.001+08:00</published><updated>2011-09-06T21:32:11.958+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-06T21:32:11.958+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TechEd" /><title>#AUTechEd 2011</title><content type="html">&lt;p&gt;The condensed version&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DAT308"&gt;Denali Always On for Mission Critical Systems&lt;/a&gt;: failing demo rather confused this one. And I don’t understand how it can be shared-nothing mirroring if it’s still based on a Windows cluster &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DAT201"&gt;Abundantly &amp;quot;Crescent&amp;quot;&lt;/a&gt;: MS’s answer for BI visualisation gets even &lt;em&gt;more &lt;/em&gt;fragmented &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DAT305"&gt;Practical Consolidation&lt;/a&gt;: when to go hard(ware), when to go virtual &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/WEB304"&gt;HTML 5 - The useful bits&lt;/a&gt;: &lt;em&gt;some&lt;/em&gt; bits you can actually use! Now! &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DEV202"&gt;Kinecting The Dots – Developing with the Kinect SDK&lt;/a&gt;: I want a Kinect &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/WPH306"&gt;What's new for Windows Phone 7.5 Games Developers XNA and Silverlight&lt;/a&gt;: it’s not either/or any more &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/WPH201"&gt;What's new in Windows Phone 7.5 for End Users and Enterprises&lt;/a&gt;: finally, targeted (‘private’) deployments &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/WEB308"&gt;There is no Web: HTML5 Offline, NoSQL and MVC 3&lt;/a&gt;: offline support not there yet. Avoid for now. No, really. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DAT303"&gt;Killer Real-World PowerPivot Examples&lt;/a&gt;: Grant is insane &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/WEB305"&gt;JavaScript with a view – advancing client side code&lt;/a&gt;: viewmodel driven MVVM for JS is a reality. Use it &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/VOC208"&gt;Science of Great UI&lt;/a&gt;: it &lt;em&gt;is&lt;/em&gt; a science. It &lt;em&gt;is&lt;/em&gt; important. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DAT311"&gt;Data Dashboards using Microsoft BI&lt;/a&gt;: why use the right tool for the job when you can just keep hacking till it works? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;b&gt;Updated&lt;/b&gt; Links now point to Channel 9 site, where the videos will end up&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-156044347681261056?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/b8w19npe0-0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/156044347681261056/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=156044347681261056" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/156044347681261056?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/156044347681261056?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/09/auteched-2011.html" title="#AUTechEd 2011" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0EFQXk6eCp7ImA9WhdXEEU.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-3804649652728939410</id><published>2011-08-23T15:46:00.000+08:00</published><updated>2011-08-23T15:46:50.710+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-23T15:46:50.710+08:00</app:edited><title>IIS WebAdministration module failing with 80040154</title><content type="html">Apart from the &lt;a href="http://www.iisworkstation.com/2009/06/troubleshooting-iis-powershell-module.html"&gt;normal stuff&lt;/a&gt; about the IIS 7 powershell module failing because it's not registered, elevated or you've not allowed the execution of scripts in your powershell session, there's one more little gotcha:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;Get-Website : Retrieving the COM class factory for component with CLSID {688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error: 80040154.&lt;/blockquote&gt;&lt;br /&gt;
...which is that the COM objects are only registered for x64 (if on an x64 machine), so if you're running a 32 bit PowerShell prompt (for various reasons related to VS GDR) you'll get the error above :-(&lt;br /&gt;
&lt;br /&gt;
See &lt;a href="http://stackoverflow.com/questions/3501001/windows-powershell-snap-in-for-iis-fails-on-32-bit"&gt;http://stackoverflow.com/questions/3501001/windows-powershell-snap-in-for-iis-fails-on-32-bit&lt;/a&gt; for some unsavory workarounds, or just run as x64 if you want it to actually work :-(&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-3804649652728939410?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/FopLsvbAlng" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/3804649652728939410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=3804649652728939410" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3804649652728939410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3804649652728939410?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/08/iis-webadministration-module-failing.html" title="IIS WebAdministration module failing with 80040154" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUAGRX4-eSp7ImA9WhdXEEs.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-52527074698025047</id><published>2011-08-23T10:48:00.000+08:00</published><updated>2011-08-23T10:48:44.051+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-23T10:48:44.051+08:00</app:edited><title>What proxy is 'automatically detect settings' actually giving me?</title><content type="html">Chrome doesn't seem to like the 'automatically detect settings' (at least not where I am right now), so I have to change over to have an explicitly configured proxy.&lt;br /&gt;
&lt;br /&gt;
But what to enter? PowerShell to the rescue:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;[System.Net.WebRequest]::DefaultWebProxy.GetProxy("http://www.test.com")&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
...tells you what proxy the system will use for the uri provided, and that's pretty much the only one you ever have to worry about. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-52527074698025047?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/vIq5x1ukwtY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/52527074698025047/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=52527074698025047" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/52527074698025047?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/52527074698025047?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/08/what-proxy-is-automatically-detect.html" title="What proxy is 'automatically detect settings' actually giving me?" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEcEQ3c4cSp7ImA9WhdQF0w.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-439477002322586525</id><published>2011-08-19T08:00:00.000+08:00</published><updated>2011-08-19T08:00:02.939+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-19T08:00:02.939+08:00</app:edited><title>Clustered Hyper-V Live Migration for $450</title><content type="html">&lt;p&gt;Well, ok, not counting the MSDN licence I had to play with this, but the point is thanks to the iSCSI support in Windows 2008 R2 (initiator &lt;em&gt;and target&lt;/em&gt;), you can now build test clusters without having to have a ‘real’ (as in expensive) shared disk array, so you too can amaze your friends by live-migrating a virtual machine in front of their very eyes, or dispel your own lingering doubts that this stuff is all smoke and mirrors.&lt;/p&gt;  &lt;p&gt;I used:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;3x old Dell Optiplex 745’s that we got for a song&lt;/li&gt;    &lt;li&gt;A 100mb hub I borrowed from IT&lt;/li&gt;    &lt;li&gt;Er… that’s it&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Using the &lt;a href="http://blogs.technet.com/b/josebda/archive/2011/04/04/microsoft-iscsi-software-target-3-3-for-windows-server-2008-r2-available-for-public-download.aspx"&gt;Microsoft iSCSI target for Windows Server 2008 R2&lt;/a&gt;, one box pretends to be a SAN. You could use Windows Storage Server, or a high-end NAS that supported iSCSI also.&lt;/p&gt;  &lt;p&gt;The other two boxes I stuck Windows 2008 R2 with Hyper-V role. I could have used Hyper-V server. Using the out-of-the-box iSCSI &lt;em&gt;initiator&lt;/em&gt;, I bound both of them to virtual drives I fronted up from the storage server, and after a few goes made a cluster.&lt;/p&gt;  &lt;p&gt;I’m not going to do the blow by blow, because there’s actually a couple of really good posts on doing this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="http://www.servercare.nl/Lists/Posts/Post.aspx?ID=61" href="http://www.servercare.nl/Lists/Posts/Post.aspx?ID=61"&gt;http://www.servercare.nl/Lists/Posts/Post.aspx?ID=61&lt;/a&gt; (read all three in this series)&lt;/li&gt;    &lt;li&gt;&lt;a title="http://blogs.technet.com/b/josebda/archive/tags/iscsi/" href="http://blogs.technet.com/b/josebda/archive/tags/iscsi/"&gt;http://blogs.technet.com/b/josebda/archive/tags/iscsi/&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;…though you will have to wade through them a bit, because the landscape has been changing, but before you know (well, it took maybe a few days, on and off) you have a VM flitting from box to box like a sprite[1].&lt;/p&gt;  &lt;p&gt;Couple of things I will mention:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The doco says you can’t do this with only one NIC per box, but you can. Wouldn’t want to in production, sure, but you can&lt;/li&gt;    &lt;li&gt;Though experience I suggest that the safest course is to &lt;em&gt;only &lt;/em&gt;have the quorum disk target attached when creating the cluster (and add more disks later). That’ll prevent the wrong disk being used as the quorum disk, which I couldn’t work out how to prevent otherwise&lt;/li&gt;    &lt;li&gt;If you destroy the cluster (as I did, several times, when it kept getting the disks round the wrong way) and find your machines don’t talk to each other any more, try removing them from the domain and re-adding. Worked for me&lt;/li&gt;    &lt;li&gt;If something doesn’t work, don’t be an idiot like me and later try exactly the same thing again and waste a whole day rebuilding everything. Try it a different way :-/&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font size="1"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="1"&gt;[1] The actual moment of cut-over took the VM out for about 4 seconds, which isn’t terrible considering the appallingly low-spec setup I was running: disk, heartbeat and client access all hitting one NIC though 100mb hub. It was only getting about 7Mb/s on the disk too.&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-439477002322586525?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/h9ZnSByGxvs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/439477002322586525/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=439477002322586525" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/439477002322586525?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/439477002322586525?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/08/clustered-hyper-v-live-migration-for.html" title="Clustered Hyper-V Live Migration for $450" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUUGRXc7cCp7ImA9WhdQFEQ.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-571364024648754328</id><published>2011-08-16T20:20:00.001+08:00</published><updated>2011-08-16T20:20:24.908+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-16T20:20:24.908+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><title>Custom Folders in SQL Server Management Studio</title><content type="html">&lt;p&gt;It’s about bloody time, but it &lt;a href="http://www.sqltreeo.com/wp/dowload-free-ssms-add-in-to-create-own-folder-for-database-objects/"&gt;took a 3rd party to hack it together&lt;/a&gt;. This really should be out-of-the-box behaviour.&lt;/p&gt;  &lt;p&gt;I like the way he’s used extended properties as the persistence medium, rather than, say, a table with a special name. It’s an approach I’ve used myself for other extensions to the standard schema metadata, like for my &lt;a href="http://piers7.blogspot.com/2009/03/easy-upserts-in-ssis-2005.html"&gt;Upsert View Generator&lt;/a&gt; (which is long overdue an updated post).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-571364024648754328?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/Gkovb3Mjrvk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/571364024648754328/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=571364024648754328" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/571364024648754328?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/571364024648754328?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/08/custom-folders-in-sql-server-management.html" title="Custom Folders in SQL Server Management Studio" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUMFRH8yeCp7ImA9WhdQFEQ.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-3059236587196248639</id><published>2011-07-01T21:00:00.000+08:00</published><updated>2011-08-16T20:23:35.190+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-16T20:23:35.190+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><title>Model-first with Entity Framework and Oracle 11g (Part 2)</title><content type="html">&lt;p&gt;So having given up on the Oracle provider for now, and because people had said good things about them, I tried devArt’s dotConnect:&lt;/p&gt;  &lt;pre&gt;-- Table &amp;quot;Customers&amp;quot;&lt;br /&gt;CREATE TABLE &amp;quot;Customers&amp;quot;  ( &lt;br /&gt;    &amp;quot;Id&amp;quot; NUMBER(10) NOT NULL,&lt;br /&gt;    &amp;quot;FirstName&amp;quot; VARCHAR2(50) NOT NULL,&lt;br /&gt;    &amp;quot;AnInteger&amp;quot; NUMBER(10) NOT NULL,&lt;br /&gt;    &amp;quot;ALong&amp;quot; NUMBER(18) NOT NULL,&lt;br /&gt;    &amp;quot;IsSomethingTrue&amp;quot; NUMBER(1) NOT NULL,&lt;br /&gt;    PRIMARY KEY (&amp;quot;Id&amp;quot;)&lt;br /&gt;)&lt;br /&gt;/&lt;br /&gt;CREATE SEQUENCE &amp;quot;Customers_SEQ&amp;quot;&lt;br /&gt;/&lt;br /&gt;CREATE OR REPLACE TRIGGER &amp;quot;Customers_INS_TRG&amp;quot;&lt;br /&gt;    BEFORE INSERT ON &amp;quot;Customers&amp;quot; FOR EACH ROW&lt;br /&gt;BEGIN&lt;br /&gt;    SELECT &amp;quot;Customers_SEQ&amp;quot;.NEXTVAL INTO :NEW.&amp;quot;Id&amp;quot; FROM DUAL;&lt;br /&gt;END;&lt;br /&gt;/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Better. We got our sequence triggers, and some slightly saner data type choices. We've still got the casing problem (and no check constraints for our boolean flag), but &lt;em&gt;we can fix that now&lt;/em&gt; because the devArt DDL generation template is a &lt;strong&gt;real&lt;/strong&gt; T4 template, not just a stub:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-sW1pfxsqCj4/Tgl5t7doWHI/AAAAAAAAANI/CKrsrkii8hY/image%25255B4%25255D.png?imgmax=800" width="390" height="97" /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You’ll find yours in C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen. There’s not loads in there, all the real work is in the include file in .\Entity Framework Tools\Templates\Includes\&lt;strong&gt;Devart SSDLToOracle.ttinclude&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A quick case-conversion modification to the the OracleGenerator class:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;	public override string GetValidIdentifier(string identifier) {&lt;br /&gt;&lt;br /&gt;		identifier = base.GetValidIdentifier(identifier);&lt;br /&gt;		return ToOracleCase(identifier);&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	public static string ToOracleCase(string value){&lt;br /&gt;		StringBuilder output = new StringBuilder();&lt;br /&gt;		bool waslower = false;&lt;br /&gt;		foreach (var c in value.ToCharArray())&lt;br /&gt;		{&lt;br /&gt;			bool isLower = char.IsLower(c);&lt;br /&gt;			if(waslower &amp;amp;&amp;amp; !isLower)&lt;br /&gt;				output.Append('_');&lt;br /&gt;			&lt;br /&gt;			output.Append(Char.ToUpper(c));&lt;br /&gt;			waslower = char.IsLower(c);&lt;br /&gt;		}&lt;br /&gt;		return output.ToString();&lt;br /&gt;	}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;...and we are ready to go (ok, it's a crude implementation, but look, we are off and away):&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;-- Table &amp;quot;CUSTOMERS&amp;quot;&lt;br /&gt;CREATE TABLE &amp;quot;CUSTOMERS&amp;quot;  ( &lt;br /&gt;    &amp;quot;ID&amp;quot; NUMBER(10) NOT NULL,&lt;br /&gt;    &amp;quot;FIRST_NAME&amp;quot; VARCHAR2(50) NOT NULL,&lt;br /&gt;    &amp;quot;AN_INTEGER&amp;quot; NUMBER(10) NOT NULL,&lt;br /&gt;    &amp;quot;ALONG&amp;quot; NUMBER(18) NOT NULL,&lt;br /&gt;    &amp;quot;IS_SOMETHING_TRUE&amp;quot; NUMBER(1) NOT NULL,&lt;br /&gt;    PRIMARY KEY (&amp;quot;ID&amp;quot;)&lt;br /&gt;)&lt;br /&gt;/&lt;br /&gt;CREATE SEQUENCE &amp;quot;CUSTOMERS__SEQ&amp;quot;&lt;br /&gt;/&lt;br /&gt;CREATE OR REPLACE TRIGGER &amp;quot;CUSTOMERS__INS_TRG&amp;quot;&lt;br /&gt;    BEFORE INSERT ON &amp;quot;CUSTOMERS&amp;quot; FOR EACH ROW&lt;br /&gt;BEGIN&lt;br /&gt;    SELECT &amp;quot;CUSTOMERS__SEQ&amp;quot;.NEXTVAL INTO :NEW.&amp;quot;ID&amp;quot; FROM DUAL;&lt;br /&gt;END;&lt;br /&gt;/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Much&lt;/strong&gt; better.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;Update: The next day I realised I’d made a cardinal error. All any of this does is change the generated DDL, not the store schema in the EDMX model. I had to do that separately, which rather defeated the point of what I was trying to do. In the end I gave up, went database-first and wrote an XSLT that performs a PascalCasing conversion on the conceptual model object / attribute names. And re-mapped any badly mapped types. What a PITA.&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-3059236587196248639?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/oistHzkUIOg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/3059236587196248639/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=3059236587196248639" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3059236587196248639?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3059236587196248639?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/07/model-first-with-entity-framework-and.html" title="Model-first with Entity Framework and Oracle 11g (Part 2)" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-sW1pfxsqCj4/Tgl5t7doWHI/AAAAAAAAANI/CKrsrkii8hY/s72-c/image%25255B4%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEMER3Y5eCp7ImA9WhZaE0g.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-7883598028845220074</id><published>2011-06-29T21:00:00.000+08:00</published><updated>2011-06-29T21:00:06.820+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-29T21:00:06.820+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><title>Model-first with Entity Framework and Oracle 11g (Part 1)</title><content type="html">&lt;p&gt;In the &lt;em&gt;very latest beta release&lt;/em&gt; of the Oracle .Net drivers (&lt;a href="http://www.oracle.com/technetwork/topics/dotnet/downloads/oracleefbeta-302521.html"&gt;11.2.0.2.30&lt;/a&gt;), Oracle now ‘supports’ Entity Framework (database-first or model-first) and Linq-to-entities. Oh, and 32bit only for now. &lt;/p&gt;  &lt;p&gt;&lt;em&gt;(If you’re tempted to try this, and get a &lt;/em&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?messageID=9427846"&gt;&lt;em&gt;'ORA-00904: &amp;quot;SUBPROGRAM_ID&amp;quot;: invalid identifier' error&lt;/em&gt;&lt;/a&gt;&lt;em&gt; it’s probably because you – as a developer - are using 10g Express Edition, which isn’t yet supported. You can wait for the EF beta 2 (soon, &lt;/em&gt;&lt;a href="http://forums.oracle.com/forums/message.jspa?messageID=9593474#9593474"&gt;&lt;em&gt;allegedly&lt;/em&gt;&lt;/a&gt;&lt;em&gt;), or alternatively you can download &lt;/em&gt;&lt;a href="http://www.oracle.com/technetwork/database/express-edition/11gxe-beta-download-302519.html"&gt;&lt;em&gt;11g Express Edition&lt;/em&gt;&lt;/a&gt;&lt;em&gt; which is also in beta. And 32 bit only (on Windows, anyway). Oh, and make sure you install the ODAC &lt;u&gt;after&lt;/u&gt; you install XE, or you’ll get the wrong Oracle home as your default on your path, and you’ll get errors in Visual Studio setting up Oracle database connections)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Prior to EF I’ve been quite happy doing database-first development in the SQL Server world, mostly because the visual tooling (database diagrams and the like) has been pretty good, and because of the type fidelity with mainstream languages (esp. .net) there’s relatively little loss of intent when you derive a model from the schema.&lt;/p&gt;  &lt;p&gt;In the Oracle world of course this is very different. I’ve been massively underwhelmed with the quality of the tooling for schema design, and Oracle’s unconventional[1] stance on 4-byte integer and boolean data types (i.e. lack thereof) means that any model derived from the schema is going to need a fair bit of tweaking the metadata. That and fixing up all the SHOUTING_IDENTIFIERS.&lt;/p&gt;  &lt;p&gt;So for Oracle, model-first looks like a &lt;u&gt;really good idea&lt;/u&gt;. Unfortunately, in the current beta at least, Oracle’s support for this is pretty lame:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;All integer types are written out as Number(38,0) (irritating) &lt;/li&gt;    &lt;li&gt;Sequences are not generated for identity fields (really painful) &lt;/li&gt;    &lt;li&gt;The PascalCasing of your entities is preserved in the database schema (&lt;strong&gt;totally unusable&lt;/strong&gt;). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;e.g.:&lt;/p&gt;  &lt;pre&gt;-- Creating table 'Customers'&lt;br /&gt;CREATE TABLE &amp;quot;myschema&amp;quot;.&amp;quot;Customers&amp;quot; (&lt;br /&gt;   &amp;quot;Id&amp;quot; number(38,0) NOT NULL,&lt;br /&gt;   &amp;quot;FirstName&amp;quot; nvarchar2(50) NOT NULL,&lt;br /&gt;   &amp;quot;AnInteger&amp;quot; number(38,0) NOT NULL,&lt;br /&gt;   &amp;quot;ALong&amp;quot; number(38,0) NOT NULL,&lt;br /&gt;   &amp;quot;IsSomethingTrue&amp;quot; number(38,0) NOT NULL&lt;br /&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Why unusable? Because, as any Oracle developer will tell you with a bitter look, Oracle is &lt;strong&gt;case sensitive&lt;/strong&gt;. Generally when you query it it all works &lt;em&gt;as if&lt;/em&gt; your query was upper-cased for you: &lt;font face="Consolas"&gt;&lt;strong&gt;select * from mytable&lt;/strong&gt;&lt;/font&gt; works against &lt;strong&gt;MYTABLE&lt;/strong&gt;. But if you use &lt;em&gt;Mixed Case&lt;/em&gt; and create a MyTable you’d have to write &lt;font face="Consolas"&gt;&lt;strong&gt;select * from “MyTable”&lt;/strong&gt;&lt;/font&gt; (note the quotes) &lt;strong&gt;and get the capitalization right&lt;/strong&gt;. Yeah, you can see how much fun you could have with this, and it’s the same with columns. So stick to the SHOUTING_IDENTIFIERS convention, or suffer the horrible consequences. It’s ok, I didn’t know either.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So what any sane SSDL / DDL generation template would do would do a conversion, right? Entities named MyTable would spit out a table called MY_TABLE, and the MyTableId attribute would be a MY_TABLE_ID column. But no.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Worse than that, because Oracle’s implemented the entire generation process in a workflow, not in the T4 template (which is a stub) &lt;strong&gt;you can’t fix this on your own&lt;/strong&gt;. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That’s about where I gave up on Oracle. Bastards.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Next time: 3rd party drivers to the rescue!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;font size="1"&gt;[1] I’m trying to be polite. Prehistoric would be more apt. &lt;a href="http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0000927.htm"&gt;DB2&lt;/a&gt;, &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html"&gt;MySql&lt;/a&gt;, &lt;a href="http://www.postgresql.org/docs/8.0/static/datatype.html#DATATYPE-INT"&gt;Postgres&lt;/a&gt; (and SQL Server of course) have 4 byte integers &lt;em&gt;because that’s what applications / CPUs actually use&lt;/em&gt;. Oracle act like it’s still 1990 and the ‘database IS the application’&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-7883598028845220074?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/GRXpdIhLI6g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/7883598028845220074/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=7883598028845220074" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/7883598028845220074?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/7883598028845220074?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/06/model-first-with-entity-framework-and.html" title="Model-first with Entity Framework and Oracle 11g (Part 1)" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEIHQnc4eSp7ImA9WhZUFEw.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-1589046470863049410</id><published>2011-06-07T10:08:00.001+08:00</published><updated>2011-06-07T10:08:53.931+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-07T10:08:53.931+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><title>Australian Dev User Groups</title><content type="html">&lt;p&gt;I was looking for (and failed to find) a Perth Java User Group, and came across &lt;a href="http://www.builderau.com.au/usergroup/"&gt;this list in builder.com.au&lt;/a&gt;. If accurate it seems to depict a bleak state for Java, loosing out 4:1 to .Net in user group count terms:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.builderau.com.au/usergroup/"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-4C5o6UbG1ik/Te2IM8NWIlI/AAAAAAAAANE/T7gPLeCGOXk/image%25255B4%25255D.png?imgmax=800" width="327" height="187" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ok, &lt;em&gt;massive&lt;/em&gt; caveats apply. Number of user groups is a terrible metric, maybe the Java ones have much higher membership / do more with less / do everything online, or maybe they’re all so good they don’t need user groups unlike the poor fumbling .Net developers. But I don’t think so…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-1589046470863049410?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/hijzRWSVB4M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/1589046470863049410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=1589046470863049410" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1589046470863049410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1589046470863049410?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/06/australian-dev-user-groups.html" title="Australian Dev User Groups" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-4C5o6UbG1ik/Te2IM8NWIlI/AAAAAAAAANE/T7gPLeCGOXk/s72-c/image%25255B4%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEMEQXw6eSp7ImA9WhZVGUo.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-7705840991909757590</id><published>2011-06-02T09:00:00.000+08:00</published><updated>2011-06-02T09:00:00.211+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-02T09:00:00.211+08:00</app:edited><title>“PhpStorm 2.1 doesn't work too nice on my Windows + Samba anymore”</title><content type="html">&lt;p&gt;Got a really bizarre email from JetBrain’s bug tracking system the other day: a ‘won’t be fixed’ for a bug I had &lt;em&gt;absolutely&lt;/em&gt; no interest in.&lt;/p&gt;  &lt;p&gt;Like many users, I’d enabled notifications for ‘issues reported by me’. &lt;a href="http://youtrack.jetbrains.net/issue/JT-9769?query=PhpStorm+2.1+doesn%27t+work+too+nice+on+my+Windows+%2B+Samba+anymore#tab=Linked%20Issues"&gt;Turns out&lt;/a&gt; that &lt;em&gt;someone&lt;/em&gt; had registered a user with the name ‘me’…&lt;/p&gt;  &lt;p&gt;…yup…&lt;/p&gt;  &lt;p&gt;…and so managed to spam the entire registered user base when anything happened to any of their bugs :-/ So some fairly serious design failure there: user-entered data being mistaken as a control sequence - basically SQL injection (in spirit, at least). &lt;/p&gt;  &lt;p&gt;Good job he didn’t register as &lt;a href="http://xkcd.com/327/"&gt;Little Bobby Tables&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font size="1"&gt;PS: Of course this is all a bit passé compared to &lt;/font&gt;&lt;a href="http://alicebobandmallory.com/articles/2010/09/23/did-little-bobby-tables-migrate-to-sweden"&gt;&lt;font size="1"&gt;hacking the electoral role&lt;/font&gt;&lt;/a&gt;    &lt;br /&gt;&lt;font size="1"&gt;PPS: Why isn’t &lt;/font&gt;&lt;a href="http://en.wikipedia.org/wiki/Taint_checking"&gt;&lt;font size="1"&gt;data tainting&lt;/font&gt;&lt;/a&gt;&lt;font size="1"&gt; a compulsory part of all mainstream languages these days?&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-7705840991909757590?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/cp8hXXXbmqA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/7705840991909757590/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=7705840991909757590" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/7705840991909757590?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/7705840991909757590?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/06/phpstorm-21-doesn-work-too-nice-on-my.html" title="“PhpStorm 2.1 doesn&amp;#39;t work too nice on my Windows + Samba anymore”" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUUEQXs6eCp7ImA9WhZVF0w.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-286600950005781676</id><published>2011-05-30T09:00:00.000+08:00</published><updated>2011-05-30T09:00:00.510+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-30T09:00:00.510+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dynamics CRM" /><title>Permissions Issues in Dynamics CRM 2011 when Users Inherit Roles from Teams</title><content type="html">&lt;p&gt;Setting up a CRM demo I noticed what appears to be a problem in the CRM 2011 security model which affects users whom only inherit a Security Role from their membership in a Team, and have no roles of their own.&lt;/p&gt;  &lt;p&gt;My user is in a Team, and the Team has the out-of-the-box Customer Service Representative role. But my user can’t create a Service Activity like he should be able to:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/__udjOzKZGww/TdH5KO2oGpI/AAAAAAAAAMk/XpXrsYPq5NI/image%5B13%5D.png?imgmax=800" width="453" height="166" /&gt;&lt;/p&gt;  &lt;p&gt;I &lt;em&gt;thought&lt;/em&gt; the team permissions were right for creating Activities, but MSDN just has a ‘coming soon page’ for both &lt;a href="http://msdn.microsoft.com/en-us/library/gg309743.aspx"&gt;the roles&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/gg309366.aspx"&gt;doesn’t even list the Activity entity&lt;/a&gt; so I wasn’t getting much help there.&lt;/p&gt;  &lt;p&gt;Some error dialogs in CRM have a little ‘view log’ button, which helps, but this one didn’t. However the TechNet article ‘&lt;a href="http://technet.microsoft.com/en-us/magazine/2009.08.dynamics.aspx"&gt;Troubleshooting Microsoft Dynamics CRM&lt;/a&gt;’ was quite helpful here (written for CRM 4.0 but much is still relevant), describing how you &lt;a href="http://technet.microsoft.com/en-us/magazine/2009.08.dynamics.aspx#id0350023"&gt;activate the detailed error dialog&lt;/a&gt; by modifying this setting in the app.config:&lt;/p&gt; &lt;code&gt;&amp;lt;add key=&amp;quot;DevErrors&amp;quot; value=&amp;quot;On&amp;quot;/&amp;gt;&lt;/code&gt;   &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/__udjOzKZGww/TdH5LKifvAI/AAAAAAAAAMo/9RVOAq-Rs54/image%5B4%5D.png?imgmax=800" width="326" height="195" /&gt;&lt;/p&gt;  &lt;p&gt;This gave me something a bit more concrete to go on:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: 00000000-0000-0000-0000-000000000000, OwnerId: {blah}, OwnerIdType: 8 and CallingUser: {blah}. ObjectTypeCode: 2500, objectBusinessUnitId: {blah}, AccessRights: CreateAccess &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ok, so I can’t create something. But interestingly a bit of poking about in the metadata schema in the database (Metadata.Entity) reveals ObjectTypeCode 2500 is &lt;em&gt;not&lt;/em&gt; actually Activity, as I suspected, but UserEntityUISettings. &lt;/p&gt;  &lt;p&gt;Hmm. The team’s got permissions for that too I thought:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/__udjOzKZGww/TdH5LwNIHoI/AAAAAAAAAMs/NhOIwkOC14s/image%5B18%5D.png?imgmax=800" width="359" height="40" /&gt;&lt;/p&gt;  &lt;p&gt;... but that permission can &lt;em&gt;only &lt;/em&gt;be applied at the user level. So I wondered if it wasn’t transitive over the Team correctly, and added the user directly to the role. &lt;/p&gt;  &lt;p&gt;And then it all worked.&lt;/p&gt;  &lt;p&gt;Perhaps there is an explanation somewhere, but I’m damned if I can find it. Services and Service Activities are new in 2011 and seem to be skipped entirely by the two CRM books I looked at. There is &lt;em&gt;some &lt;/em&gt;documentation around the permissions model, but it’s incomplete, and most blog posts I’ve read seem to suggest diagnosing issues is a bit of a crapshoot, which is pretty piss poor for a business-orientated application if you ask me. And I’d hate to have had to diagnose this in the cloud, without access to the database...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-286600950005781676?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/nD5MgKLmn3I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/286600950005781676/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=286600950005781676" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/286600950005781676?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/286600950005781676?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/05/permissions-issues-in-dynamics-crm-2011.html" title="Permissions Issues in Dynamics CRM 2011 when Users Inherit Roles from Teams" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/__udjOzKZGww/TdH5KO2oGpI/AAAAAAAAAMk/XpXrsYPq5NI/s72-c/image%5B13%5D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;CEMEQXYyfip7ImA9WhZVEUw.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-6764496707521948261</id><published>2011-05-23T09:00:00.000+08:00</published><updated>2011-05-23T09:00:00.896+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-23T09:00:00.896+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><title>More whinging about Hash Aggregate</title><content type="html">&lt;p&gt;I previously posted on why &lt;a href="http://piers7.blogspot.com/2011/03/avoid-hash-aggregation.html"&gt;Hash Aggregate is to be avoided&lt;/a&gt; if possible. Unfortunately Hash Aggregate vs. Stream Aggregate appears to be an ‘all or nothing’ proposal. And that sucks.&lt;/p&gt;  &lt;p&gt;A Stream Aggregate can be relatively cheap (in terms of memory pressure) because it can leverage the ordering (typically clustered index ordering) of the input data and aggregate on-the-fly. By contrast the Hash aggregate has to cope with completely &lt;em&gt;disordered&lt;/em&gt; data streams, so must buffer all the output aggregates in memory until the input data has been entirely read:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;The other aggregation operator, hash aggregate, is similar to hash join.&amp;#160; It does not require (or preserve) sort order, requires memory, and is blocking (i.e., it does not produce any results until it has consumed its entire input).&amp;#160; Hash aggregate excels at efficiently aggregating very large data sets.”      &lt;br /&gt;[Craig Freedman - &lt;a title="http://blogs.msdn.com/b/craigfr/archive/2006/09/20/hash-aggregate.aspx" href="http://blogs.msdn.com/b/craigfr/archive/2006/09/20/hash-aggregate.aspx"&gt;http://blogs.msdn.com/b/craigfr/archive/2006/09/20/hash-aggregate.aspx&lt;/a&gt; ]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is a good strategy because:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;It copes with totally unordered data &lt;/li&gt;    &lt;li&gt;Provided you are aggregating to a significantly higher grain than the source data, the volume of aggregates in the hash (and hence memory consumption) can be relatively small. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In my case, of course, the latter isn’t true: I’m aggregating across a &lt;em&gt;significant&lt;/em&gt; amount of data, but not aggregating very much, so I am experiencing &lt;em&gt;vast&lt;/em&gt; quantities of tempdb spill.&lt;/p&gt;  &lt;p&gt;My input data is &lt;em&gt;partially &lt;/em&gt;aligned to the aggregation (the most significant column is sorted correctly), so you’d expect that the aggregation would be able to leverage that smartly, to output aggregates when they were clearly ‘done’. So, for example, if you had a clustered index on Month/Day/Category, and you were doing sum(something) GROUP BY Month, Category, you and I both know that after you’ve finished spooling data for any given month, you can output all those buckets, rather than hang on to them waiting for more. Unfortunately this doesn’t happen, which means given enough data, something will spill to disk:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“if we run out of memory, we must begin spilling rows to tempdb.&amp;#160; We spill one or more buckets or partitions including any partially aggregated results along with any additional new rows that hash to the spilled buckets or partitions”     &lt;br /&gt;[Craig’s blog again, same link as before]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;One can only hope it’s the &lt;em&gt;older&lt;/em&gt; buckets that get spilt first, but even so, when this happens you are taking the IO hit of streaming all that aggregate data to disk and then subsequently loading it all back in again. Ouch. Or you force the stream aggregate (using a hint) and take the pain of the sort. More ouch.&lt;/p&gt;  &lt;p&gt;For many workloads this probably isn’t much of an issue, but for my data warehouse this is starting to look like a major, major bottleneck.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-6764496707521948261?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/OET0dV5d-y8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/6764496707521948261/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=6764496707521948261" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/6764496707521948261?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/6764496707521948261?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/05/more-whinging-about-hash-aggregate.html" title="More whinging about Hash Aggregate" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEMER3s8fSp7ImA9WhZWGE0.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-2948842657597672276</id><published>2011-05-19T20:00:00.000+08:00</published><updated>2011-05-19T20:00:06.575+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-19T20:00:06.575+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dynamics CRM" /><title>Setting up CRM 2011? Set the Calender format *first*</title><content type="html">&lt;p&gt;When you create a new Dynamics CRM 2011 organizational instance, the localization settings for that Organization default to US format, &lt;strong&gt;totally ignoring&lt;/strong&gt; the settings of the installing user, defaults for the server etc…&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/__udjOzKZGww/TdNFIYuW5gI/AAAAAAAAAMw/MDxjO9hFUwM/image%5B10%5D.png?imgmax=800" width="372" height="233" /&gt;&lt;/p&gt;  &lt;p&gt;You can change this in Settings \ Administration \ System Settings \ Format, but make sure you do so &lt;strong&gt;before you add any users to the CRM instance&lt;/strong&gt;, because when you change it it doesn’t apply retrospectively to users already created. Hardly intuitive, I think you’ll agree, and you’d at very least expect a note (or warning) on the dialog that all you are changing (apparently) is the new user default.&lt;/p&gt;  &lt;p&gt;eg: After changing to Australian format, new users correctly see this:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/__udjOzKZGww/TdNFJeHTB8I/AAAAAAAAAM0/OV9LnbBrJoQ/image%5B15%5D.png?imgmax=800" width="197" height="81" /&gt;&lt;/p&gt;  &lt;p&gt;However, a user &lt;em&gt;created before the change&lt;/em&gt; still sees this:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/__udjOzKZGww/TdNFJxDBt1I/AAAAAAAAAM4/vCDQG_ZwKnU/image%5B30%5D.png?imgmax=800" width="180" height="94" /&gt;&lt;/p&gt;  &lt;p&gt;These users must each and every one go into their dashboard options and change their &lt;em&gt;personal&lt;/em&gt; format settings to get what is now the &lt;em&gt;system&lt;/em&gt; setting.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/__udjOzKZGww/TdNFKySgx6I/AAAAAAAAAM8/XQTzrmy0KU0/image%5B20%5D.png?imgmax=800" width="140" height="155" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/__udjOzKZGww/TdNFLg71N3I/AAAAAAAAANA/cyGc_FQFZGw/image%5B25%5D.png?imgmax=800" width="332" height="290" /&gt;&lt;/p&gt;  &lt;p&gt;You’d notice this fairly early on I imagine, but you could still have created a bunch of content and a bunch of users, so this could be a real administrative pain in the arse.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-2948842657597672276?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/HXqY9NGeDoQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/2948842657597672276/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=2948842657597672276" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/2948842657597672276?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/2948842657597672276?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/05/setting-up-crm-2011-set-calender-format.html" title="Setting up CRM 2011? Set the Calender format *first*" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/__udjOzKZGww/TdNFIYuW5gI/AAAAAAAAAMw/MDxjO9hFUwM/s72-c/image%5B10%5D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;CE8DQnk7cSp7ImA9WhZWF0Q.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-1872735163789699515</id><published>2011-05-19T16:14:00.001+08:00</published><updated>2011-05-19T16:14:33.709+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-19T16:14:33.709+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>Silverlight Spy</title><content type="html">&lt;p&gt;&lt;a href="http://firstfloorsoftware.com/silverlightspy/"&gt;This&lt;/a&gt; looks cool – a &lt;a href="http://hawkeye.codeplex.com"&gt;Hawkeye&lt;/a&gt; for Silverlight apps (in and out of browser). Basic version is free.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/b/chkoenig/archive/2008/08/29/silverlight-spy.aspx"&gt;Good Overview&lt;/a&gt;, there’s also a &lt;a href="http://channel9.msdn.com/shows/Continuum/SilverlightSpy/"&gt;video on C9&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-1872735163789699515?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/OIQjD9rjXPQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/1872735163789699515/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=1872735163789699515" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1872735163789699515?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1872735163789699515?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/05/silverlight-spy.html" title="Silverlight Spy" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUEEQnk6fip7ImA9WhZWFkU.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-7671098507017543436</id><published>2011-05-18T11:00:00.000+08:00</published><updated>2011-05-18T11:00:03.716+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-18T11:00:03.716+08:00</app:edited><title>NineMSN vs IE9</title><content type="html">&lt;p&gt;NineMSN still shows up as ‘compatibility view’ in both IE 8 and 9, despite what the banner ad below might suggest:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/__udjOzKZGww/TdHk5x6xDdI/AAAAAAAAAMg/rjXKTLBtGHY/image4.png?imgmax=800" width="585" height="152" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Note: I wrote this two months ago and forgot to publish it. But it’s still true...&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-7671098507017543436?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/KxTPeugpfl8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/7671098507017543436/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=7671098507017543436" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/7671098507017543436?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/7671098507017543436?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/05/ninemsn-vs-ie9.html" title="NineMSN vs IE9" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/__udjOzKZGww/TdHk5x6xDdI/AAAAAAAAAMg/rjXKTLBtGHY/s72-c/image4.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0IBRXkycSp7ImA9WhZWFUQ.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-5750794019188996421</id><published>2011-05-17T10:32:00.001+08:00</published><updated>2011-05-17T10:32:34.799+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-17T10:32:34.799+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MDX" /><category scheme="http://www.blogger.com/atom/ns#" term="SSAS" /><title>Excel Multiselect Issues with SSAS Calculated Member</title><content type="html">&lt;p&gt;Ok, it’s an old one, but I struggled to find the right answer, so I thought it was worth a post. I knew it was an issue, and I thought I knew the answer. I was wrong.&lt;/p&gt;  &lt;p&gt;Say you create a calculated member to return some kind of item count against a dimension, a bit like this:&lt;/p&gt; &lt;code&gt;CREATE MEMBER CURRENTCUBE.[Measures].[Days Count] as (    &lt;br /&gt;count( descendants(     &lt;br /&gt;&amp;#160; [Date].[Year-Month-Date].CurrentMember,     &lt;br /&gt;&amp;#160; [Date].[Year-Month-Date].[Date]     &lt;br /&gt;)) &lt;/code&gt;  &lt;p&gt;and it works just fine when you test it&lt;/p&gt; &lt;code&gt;SELECT {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [Measures].[Days Count]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ,[Measures].[Minutes Of Day Count]     &lt;br /&gt;} ON COLUMNS     &lt;br /&gt;FROM [My Cube]     &lt;br /&gt;WHERE {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [Date].[Year-Month-Date].[Year].[2011]     &lt;br /&gt;}&lt;/code&gt;   &lt;p&gt;&lt;a href="http://lh4.ggpht.com/__udjOzKZGww/TcytjHHDflI/AAAAAAAAAMI/X-x2o01Aa6U/s1600-h/image%5B3%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/__udjOzKZGww/TcytkrXuG0I/AAAAAAAAAMM/yz4x3TDASPE/image_thumb%5B1%5D.png?imgmax=800" width="221" height="56" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;…and then you find it falls apart when someone queries the cube in Excel and uses multi-select in the pivot table filter. So you follow &lt;a href="http://www.mosha.com/msolap/articles/mdxmultiselectcalcs.htm"&gt;Mosha’s advice to fix it (using Existing)&lt;/a&gt;:&lt;/p&gt; &lt;code&gt;CREATE MEMBER CURRENTCUBE.[Measures].[Days Count] as    &lt;br /&gt;count( &lt;strong&gt;existing&lt;/strong&gt; [Date].[Year-Month-Date].[Date] ) &lt;/code&gt;  &lt;p&gt;…but then someone points out that &lt;em&gt;that doesn’t work either. &lt;/em&gt;More recent versions of Excel (2007, 2010) implement multi-select via sub-queries; with just a few days selected it generates a query that (simplified) looks a bit like this:&lt;/p&gt; &lt;code&gt;SELECT {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [Measures].[Days Count]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ,[Measures].[Minutes Of Day Count]     &lt;br /&gt;} ON COLUMNS     &lt;br /&gt;FROM (     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; SELECT (     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {[Date].[Year-Month-Date].[Date].&amp;amp;[20110101]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ,[Date].[Year-Month-Date].[Date].&amp;amp;[20110102]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; })     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ON COLUMNS&amp;#160; FROM [My Cube]     &lt;br /&gt;)     &lt;br /&gt;&lt;/code&gt;  &lt;p&gt;and executing that &lt;em&gt;doesn’t&lt;/em&gt; give you the right answer (it just counts the number of members in the dimension):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/__udjOzKZGww/TcytlbFeb8I/AAAAAAAAAMQ/7qwLcByRuRM/s1600-h/image%5B7%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/__udjOzKZGww/TcytmHSEdZI/AAAAAAAAAMU/feZM3dYIRTk/image_thumb%5B3%5D.png?imgmax=800" width="253" height="65" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So the old advice, still commonly quoted, is actually wrong. The solution (as of SSAS 2008 and onwards) is to use a dynamic named set:&lt;/p&gt; &lt;code&gt;CREATE DYNAMIC SET [Selected Days] as (    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [Date].[Year-Month-Date].[Date]     &lt;br /&gt;)     &lt;br /&gt;&lt;/code&gt;&lt;code&gt;CREATE MEMBER CURRENTCUBE.[Measures].[Days Count] as (    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; count(&lt;strong&gt;[Selected Days]&lt;/strong&gt;)     &lt;br /&gt;)&lt;/code&gt;   &lt;p&gt;I found this a bit bizarre at first, but some of the &lt;a href="http://ssas-musings.blogspot.com/2010/01/excel-and-mdx-multiselect-problems.html"&gt;posts I read&lt;/a&gt; were themselves &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/sqlanalysisservices/thread/a6b21a43-0a8c-4936-8e9a-9ac5f6fd174d/"&gt;a bit confused&lt;/a&gt; and left in the ‘existing’. This is &lt;strong&gt;not &lt;/strong&gt;required, and distracts from what’s really going on here: this works &lt;em&gt;by design &lt;/em&gt;as this is one of the problems that dynamic sets are intended to fix. A (more recent) &lt;a href="http://sqlblog.com/blogs/mosha/archive/2007/08/26/mdx-in-katmai-dynamic-named-sets.aspx"&gt;Mosha post&lt;/a&gt; spells it out:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;“Dynamic sets are not calculated once. They are calculated before each query, and, very important, in the context of that's query WHERE clause &lt;strong&gt;and subselects&lt;/strong&gt;”&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/__udjOzKZGww/TcytmzFXt3I/AAAAAAAAAMY/M66uDGGZ4oU/s1600-h/image%5B11%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/__udjOzKZGww/TcytnuolavI/AAAAAAAAAMc/gUiQVs9gdOI/image_thumb%5B5%5D.png?imgmax=800" width="276" height="98" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ah. The answer, &lt;em&gt;and&lt;/em&gt; the explanation. Finally.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-5750794019188996421?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/O8LWvH98nus" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/5750794019188996421/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=5750794019188996421" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/5750794019188996421?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/5750794019188996421?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/05/excel-multiselect-issues-with-ssas.html" title="Excel Multiselect Issues with SSAS Calculated Member" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/__udjOzKZGww/TcytkrXuG0I/AAAAAAAAAMM/yz4x3TDASPE/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;Ak8CQHY6cSp7ImA9WhZWE0w.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-2173033391516966404</id><published>2011-05-12T14:59:00.000+08:00</published><updated>2011-05-14T04:34:21.819+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-14T04:34:21.819+08:00</app:edited><title>When Tabs go Bad</title><content type="html">&lt;p&gt;Maybe it’s just me, but I don’t think a tabbed UI is cutting it any more for the New User dialog in Active Directory:&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/__udjOzKZGww/TcuFbVXRMRI/AAAAAAAAAME/8FBf5wsrZtk/image%5B6%5D.png?imgmax=800" width="442" height="223" /&gt;&lt;/p&gt;  &lt;p&gt;Also just me, but ‘Remote Desktop Services Profile’ strikes me as about twice as long as it should be for a tab header.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Update: Later I found the Active Directory Administrative Center, which is an apparently WPF-based replacement for all this, and looks much nicer. So I guess the dialog above is deprecated anyway.&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-2173033391516966404?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/vjrk0eU3ORI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/2173033391516966404/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=2173033391516966404" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/2173033391516966404?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/2173033391516966404?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/05/when-tabs-go-bad.html" title="When Tabs go Bad" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/__udjOzKZGww/TcuFbVXRMRI/AAAAAAAAAME/8FBf5wsrZtk/s72-c/image%5B6%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUEEQXw4fSp7ImA9WhZRFEU.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-3651313161425554041</id><published>2011-04-11T09:00:00.000+08:00</published><updated>2011-04-11T09:00:00.235+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-11T09:00:00.235+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="IIS" /><category scheme="http://www.blogger.com/atom/ns#" term="SSAS" /><category scheme="http://www.blogger.com/atom/ns#" term="Powershell" /><title>Configuring SSAS 2008 HTTP access on IIS 7.5 using PowerShell</title><content type="html">&lt;p&gt;…was way too much like hard work / blindly poking about in the dark, and there’s still a nasty hacky bit in the script where I gave up trying to make the IIS snap-in work, and just used appcmd, but it does actually work:&lt;/p&gt;  &lt;pre&gt;&amp;lt;#&lt;br /&gt;.Synopsis&lt;br /&gt;Configures HTTP access for SSAS on the local box&lt;br /&gt;&lt;br /&gt;.SeeAlso&lt;br /&gt;http://technet.microsoft.com/en-sg/library/gg492140(en-us).aspx&lt;br /&gt;http://learn.iis.net/page.aspx/436/powershell-snap-in-changing-simple-settings-in-configuration-sections/&lt;br /&gt;http://www.iis.net/ConfigReference/system.webServer/security/isapiCgiRestriction&lt;br /&gt;#&amp;gt;&lt;br /&gt;$ErrorActionPreference = 'stop'&lt;br /&gt;$scriptDir = split-path $myInvocation.MyCommand.Path;&lt;br /&gt;$isapiPath = &amp;quot;$scriptDir\msmdpump.dll&amp;quot;&lt;br /&gt;&lt;br /&gt;import-module WebAdministration&lt;br /&gt;cd IIS:\&lt;br /&gt;&lt;br /&gt;# Register msmdpump as a (globally) acceptable ISAPI handler&lt;br /&gt;$isapiRestrictions = Get-WebConfiguration /system.webServer/security/isapiCgiRestriction&lt;br /&gt;$handler = @($isapiRestrictions.Collection | ? { $_.description -eq 'OLAP' } )&lt;br /&gt;if(-not $handler){&lt;br /&gt;    # This way the object always appears locked?&lt;br /&gt;    # but should be fine according to http://forums.iis.net/t/1158906.aspx&lt;br /&gt;   $null = @&amp;quot;&lt;br /&gt;    $restrictions = $isapiRestrictions.GetCollection();&lt;br /&gt;    $handler = $restrictions.CreateElement('add');&lt;br /&gt;    $handler.SetAttributeValue('path', $isapiPath);&lt;br /&gt;    $handler.SetAttributeValue('allowed',$true);&lt;br /&gt;    $handler.SetAttributeValue('description','OLAP');&lt;br /&gt;    $restrictions.Add($handler);&lt;br /&gt;&amp;quot;@&lt;br /&gt;&lt;br /&gt;    # instead try&lt;br /&gt;    # http://serverfault.com/questions/134361/programmatically-add-an-isapi-extension-dll-in-iis-7-using-adsi&lt;br /&gt;    &amp;amp; &amp;quot;$env:windir\system32\inetsrv\appcmd.exe&amp;quot; set config /section:isapiCgiRestriction /+&amp;quot;[path='$isapiPath', description='OLAP',allowed='True']&amp;quot;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;# Create the app pool&lt;br /&gt;cd IIS:\AppPools&lt;br /&gt;if(-not (Test-Path OLAP)){&lt;br /&gt;    $olapAppPool = New-WebAppPool OLAP&lt;br /&gt;}else{&lt;br /&gt;    $olapAppPool = Get-Item OLAP&lt;br /&gt;}&lt;br /&gt;$olapAppPool.managedPipelineMode = 'classic'&lt;br /&gt;$olapAppPool | Set-Item&lt;br /&gt;&lt;br /&gt;# Create the website&lt;br /&gt;cd IIS:\Sites&lt;br /&gt;$defaultSite = @(dir)[0]&lt;br /&gt;cd $defaultSite.Name&lt;br /&gt;&lt;br /&gt;if(-not (Test-Path OLAP)){&lt;br /&gt;    $olapApp = New-WebApplication OLAP -physicalPath:$scriptDir&lt;br /&gt;}else{&lt;br /&gt;    $olapApp = Get-Item OLAP&lt;br /&gt;}&lt;br /&gt;$olapLocation = '{0}/{1}' -f $defaultSite.Name,$olapApp.Name&lt;br /&gt;cd OLAP&lt;br /&gt;&lt;br /&gt;# Setup the web application: first associate the app pool&lt;br /&gt;set-itemproperty $pwd -name applicationPool -value 'OLAP'&lt;br /&gt;&lt;br /&gt;# ...then enable anonymous access&lt;br /&gt;$basicAuth = Get-WebConfiguration -Filter /system.webServer/security/authentication/anonymousAuthentication&lt;br /&gt;$basicAuth.Enabled = $true&lt;br /&gt;$basicAuth | Set-WebConfiguration -Filter /system.webServer/security/authentication/anonymousAuthentication -PSPath IIS:\ -Location $olapLocation&lt;br /&gt;&lt;br /&gt;# ...and create a mapping for that handler for this web app&lt;br /&gt;$mapping = Get-WebHandler OLAP&lt;br /&gt;if(-not $mapping){&lt;br /&gt;    $mapping = New-WebHandler OLAP -ScriptProcessor:$isapiPath -Path:*.dll -Verb:* -Location:$olapLocation -PSPath:IIS:\ -Modules:IsapiModule&lt;br /&gt;}&lt;br /&gt;$mapping&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Wow. IIS administration is just as bizarre and arcane as it always was. Did someone say ‘where is the setup wizard’?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-3651313161425554041?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/jY3o5U92CyY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/3651313161425554041/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=3651313161425554041" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3651313161425554041?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3651313161425554041?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/04/configuring-ssas-2008-http-access-on.html" title="Configuring SSAS 2008 HTTP access on IIS 7.5 using PowerShell" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkMEQnsyeyp7ImA9WhZREk8.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-1355679888333465438</id><published>2011-04-08T09:00:00.000+08:00</published><updated>2011-04-08T09:00:03.593+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-08T09:00:03.593+08:00</app:edited><title>Word Team not talking to Excel Team, apparently</title><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="&amp;#39;spreadsheet&amp;#39; not in Word dictionary" border="0" alt="&amp;#39;spreadsheet&amp;#39; not in Word dictionary" src="http://lh6.ggpht.com/__udjOzKZGww/TZmImSznvII/AAAAAAAAAL8/7VFFEHc5Iw4/image%5B6%5D.png?imgmax=800" width="288" height="162" /&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-1355679888333465438?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/M2eblYXpOow" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/1355679888333465438/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=1355679888333465438" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1355679888333465438?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1355679888333465438?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/04/word-team-not-talking-to-excel-team.html" title="Word Team not talking to Excel Team, apparently" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/__udjOzKZGww/TZmImSznvII/AAAAAAAAAL8/7VFFEHc5Iw4/s72-c/image%5B6%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A04ESXk9eSp7ImA9WhZSFkk.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-1518548410872435921</id><published>2011-03-30T10:00:00.001+08:00</published><updated>2011-04-01T17:25:08.761+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-01T17:25:08.761+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><title>Avoid Hash Aggregation</title><content type="html">I’d been wondering about this, but &lt;a href="http://sqlblogcasts.com/blogs/simons/archive/2011/03/24/the-optimiser-should-understand-that-year-datecolumn-is-correlated-to-the-datecolumn.aspx"&gt;Simon Sabin&lt;/a&gt;’s recent post just spelt it out for me: Hash Aggregation is all too easy to do, but &lt;em&gt;eats performance for breakfast&lt;/em&gt;. We’re all used to the problem of SARGable arguments, right? You perform any operations on the &lt;em&gt;parameter&lt;/em&gt; not the &lt;em&gt;column&lt;/em&gt; in order to correctly hit the indexes you’d expect to hit. So for example you &lt;em&gt;wouldn’t&lt;/em&gt; do this: &lt;br /&gt;&lt;br /&gt;&lt;code&gt; select blah&lt;br /&gt; from table&lt;br /&gt; where year(datecolumn) = @myyear&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;but instead you’d do this: &lt;br /&gt;&lt;br /&gt;&lt;code&gt; select blah&lt;br /&gt; from table&lt;br /&gt; where datecolumn &amp;gt;= @myyear and datecolumn &amp;lt; dateadd(year, @myyear, 1)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Well exactly the same problem occurs with aggregates, but without the fix. Say datecolum was datetime2(0) – ie down to the second, and you want an annual aggregate of something. For example:&lt;br /&gt;&lt;br /&gt;&lt;code&gt; select year(datecolumn) as Year, itemId, sum(cost)&lt;br /&gt; from table&lt;br /&gt; group by year(datecolumn), ItemId&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Look what we did. We had to apply the function to the column, and hey presto, despite our underlying table having a clustered index in datecolumn, itemId order, our aggregation is a Hash Aggregation because &lt;strong&gt;SQL can’t infer the relationship between a Year and a DateTime&lt;/strong&gt;. It can’t use Stream Aggregation unless the data is in the right order, which it now can’t infer, and it thinks the hash is going to be cheaper than a full sort.&lt;br /&gt;&lt;br /&gt;But &lt;strong&gt;Hash Aggregation is expensive&lt;/strong&gt;, as you only have to read the doco to realise:&lt;br /&gt;&lt;blockquote&gt;For the distinct or aggregate operators, use the input to build the hash table (removing duplicates and computing any aggregate expressions). When the hash table is built, scan the table and output all entries. &lt;a title="http://technet.microsoft.com/en-us/library/ms189582.aspx" href="http://technet.microsoft.com/en-us/library/ms189582.aspx"&gt;http://technet.microsoft.com/en-us/library/ms189582.aspx&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;That hash just buffered all our data in order to do the aggregation. Opps, TempDb spill here we come…&lt;br /&gt;&lt;br /&gt;A &lt;strong&gt;Stream Aggregation &lt;/strong&gt;is much more performant because it can perform the aggregation ‘on the fly’ because the data is in order, but to do this in our example we’d have to have a calculated, indexed column ‘Year’, and indexing means it’s persisted, so bang we just added 4 bytes to our fact rows and increased my table size by about &lt;strong&gt;20%&lt;/strong&gt; (my table is not very wide, but very, very long). And I still need the existing clustered index, so we’re creating a non-clustered index and the relative cost difference for scanning the table might mean we &lt;em&gt;still &lt;/em&gt;don’t get what we want.&lt;br /&gt;&lt;br /&gt;How much worse is the Hash? I cooked up an example with some of our data against three scenarios:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;doing an annual aggregate based on munging dates into years (the group by above)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;doing the aggregate based on adding the year column and putting it in the clustered index&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/__udjOzKZGww/TZFoxpVetPI/AAAAAAAAAL4/sT83iT4VNiM/image%5B13%5D.png?imgmax=800" width="570" height="240" /&gt; &lt;br /&gt;&lt;br /&gt;88% : 12%. Quite a difference (though the rowcount here is fairly small so this may not be entirely representative).&lt;br /&gt;&lt;br /&gt;Ideally Sql would ‘see through’ the Year (and other date related functions) and deduce that it can still use the date-ordered clustered index to service a stream aggregation, and this is exactly what Simon’s &lt;a href="https://connect.microsoft.com/SQLServer/feedback/details/653206/the-optimizer-should-be-able-to-understand-the-invertability-of-built-in-intrinsics-on-dates-for-the-purposes-of-index-sargability"&gt;opened a Connect issue asking for&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;That article seems to suggest that there are workarounds, like joining to the date dimension table and grouping based on columns from that, which I tried in vain. However, this may only be relevant when you’re limiting to a subset of the data. More importantly, this is only viable if the original column was of type Date: if you had a DateTime2(0) you’d need to join against a combined Date-And-Time dimension (getting fairly large). If you had DateTime2(2), you’d need to join against a date dimension that went down to the 100’th of a second. That’s a &lt;strong&gt;big &lt;/strong&gt;dimension (3,153,600,000 rows / year).&lt;br /&gt;&lt;br /&gt;Ultimately given my real world scenario is doing lots of aggregations from the sub-minute up to the minute grain, I had to bite the bullet, and change the column in the fact table to smalldatetime (and put the seconds portion in a different column). And that seems like a really poor outcome for what you would have thought would be a bread-and-butter warehousing requirement[1].&lt;br /&gt;&lt;br /&gt;Here’s a really excellent write up of the two different operators from Craig Freedman’s blog:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/craigfr/archive/2006/09/13/752728.aspx"&gt;Stream Aggregate&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/craigfr/archive/2006/09/20/hash-aggregate.aspx"&gt;Hash Aggregate&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;[1] I’m only doing any of this &lt;em&gt;at all&lt;/em&gt; because of limitations in SSAS and trying to avoid calc-and-sum performance issues, so it’s all a bit frustrating.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-1518548410872435921?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/nbpaIKiwnDM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/1518548410872435921/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=1518548410872435921" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1518548410872435921?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1518548410872435921?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/03/avoid-hash-aggregation.html" title="Avoid Hash Aggregation" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/__udjOzKZGww/TZFoxpVetPI/AAAAAAAAAL4/sT83iT4VNiM/s72-c/image%5B13%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0YDRHk9cSp7ImA9WhZSE0s.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-1684277741920690423</id><published>2011-03-29T10:17:00.001+08:00</published><updated>2011-03-29T10:19:35.769+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-29T10:19:35.769+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><title>Static Lookup Data: Prefer CASE to JOIN when possible</title><content type="html">&lt;p&gt;Getting into the nitty-gritty of fine-tuning the datamart I’m working on now, so spending a lot of time looking at execution plans, and wondering ‘why?’. Today: lookup data.&lt;/p&gt;  &lt;p&gt;Normally in a datamart you’d denormalize as much as possible, ideally avoiding JOINs altogether, but there’s a trade-off with space and in some cases the space cost just can’t be justified. Sometimes you still have to add some lookup data (cost rates etc…) in your fact view.&lt;/p&gt;  &lt;p&gt;Given a tiny amount of lookup data (10’s of rows), I thought putting it in a little table and doing a join would be pretty performant. The lookup table will basically just sit in RAM all the time, and it’s tiny compared to the fact data so the optimizer can’t possibly it the wrong way round. And I thought searched CASE statements were expensive. Turns out they are nothing on a JOIN, even in the optimal case. &lt;/p&gt;  &lt;p&gt;Adding columns using a CASE statement &lt;em&gt;performs significantly better&lt;/em&gt; than the static lookup table strategy. Even when the CASE statement is rolled up into a table-valued function, the costs in my case are about 2:1 in favour (the TVF is successfully ‘optimized away’).&lt;/p&gt;  &lt;p&gt;In both strategies SQL has to look at each-and-every row, so I’m surprised it’s &lt;em&gt;that&lt;/em&gt; different, but I guess maybe the Hash Match is optimized for larger amounts of data (on the right side), and can’t match a CASE for trivial lookups. There’s also the cardinality to consider: a CASE devolves to a COMPUTE SCALAR, which means no change in the number of rows, but a Hash Match might output a row more than once (or drop rows) based on the number of matches on the right side of the query. I’m guessing this constraint means there’s a fundamentally cheaper way to process the data in memory.&lt;/p&gt;  &lt;p&gt;Here’s the before and after, with a relatively small number of rows (70,000 on my dev box, but it’s near exactly the same with 100+ million in the test environment):&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/__udjOzKZGww/TZFBMo2tjsI/AAAAAAAAAL0/rtIJbiYw_js/image%5B8%5D.png?imgmax=800" width="580" height="314" /&gt; &lt;/p&gt;  &lt;p&gt;Now you’ll have to excuse me, because I have some views to change…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-1684277741920690423?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/6DJGLm_ak-Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/1684277741920690423/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=1684277741920690423" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1684277741920690423?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/1684277741920690423?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/03/static-lookup-data-prefer-case-to-join.html" title="Static Lookup Data: Prefer CASE to JOIN when possible" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/__udjOzKZGww/TZFBMo2tjsI/AAAAAAAAAL0/rtIJbiYw_js/s72-c/image%5B8%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEQDRHY9cSp7ImA9WhZSEEw.&quot;"><id>tag:blogger.com,1999:blog-17332816.post-3918380220075895944</id><published>2011-03-25T09:26:00.001+08:00</published><updated>2011-03-25T09:26:15.869+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-25T09:26:15.869+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><title>Enabling Sql Server CLR Integration if not currently enabled</title><content type="html">&lt;p&gt;I don’t know, is calling RECONFIGURE unnecessarily an issue? Anyway, if you really want to only enable the integration &lt;em&gt;if it’s not already enabled&lt;/em&gt; (and maybe want to do something else at the same time):&lt;/p&gt;  &lt;pre&gt;DECLARE @config TABLE (&lt;br /&gt;	NAME sysname,&lt;br /&gt;	minimum INT,&lt;br /&gt;	maximum INT,&lt;br /&gt;	config_value INT,&lt;br /&gt;	run_value int&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;INSERT INTO @config&lt;br /&gt;EXEC sp_configure 'clr enabled'&lt;br /&gt;&lt;br /&gt;IF EXISTS (SELECT run_value FROM @config WHERE run_value = 0)&lt;br /&gt;BEGIN&lt;br /&gt;	PRINT 'Enabling CLR integration'&lt;br /&gt;	EXEC sp_configure 'clr enabled', 1;&lt;br /&gt;	RECONFIGURE;&lt;br /&gt;	EXEC sp_configure 'clr enabled'&lt;br /&gt;END&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17332816-3918380220075895944?l=piers7.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CupofT/~4/kpupdGJW6Ec" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://piers7.blogspot.com/feeds/3918380220075895944/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=17332816&amp;postID=3918380220075895944" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3918380220075895944?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/17332816/posts/default/3918380220075895944?v=2" /><link rel="alternate" type="text/html" href="http://piers7.blogspot.com/2011/03/enabling-sql-server-clr-integration-if.html" title="Enabling Sql Server CLR Integration if not currently enabled" /><author><name>piers7</name><uri>http://www.blogger.com/profile/11186470645521299750</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry></feed>

