<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-18284077</atom:id><lastBuildDate>Tue, 16 Mar 2010 13:39:15 +0000</lastBuildDate><title>John Socha-Leialoha's Blog</title><description>Here you'll find my musings about software.</description><link>http://www.socha.com/blogs/john/</link><managingEditor>noreply@blogger.com (John Socha-Leialoha)</managingEditor><generator>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-8537297328773258404</guid><pubDate>Tue, 16 Mar 2010 13:39:00 +0000</pubDate><atom:updated>2010-03-16T06:39:15.492-07:00</atom:updated><title>This blog has moved</title><description>
       This blog is now located at http://blogs.socha.com/.
       You will be automatically redirected in 30 seconds, or you may click &lt;a href='http://blogs.socha.com/'&gt;here&lt;/a&gt;.

       For feed subscribers, please update your feed subscriptions to
       http://blogs.socha.com/feeds/posts/default.
  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-8537297328773258404?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2010/03/this-blog-has-moved.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-1344827243793420927</guid><pubDate>Tue, 02 Mar 2010 19:23:00 +0000</pubDate><atom:updated>2010-03-04T09:34:58.679-08:00</atom:updated><title>Upgrading Team Foundation Server 2008 Reports to 2010, Part III</title><description>This is likely to be my final post on upgrading reports for Team Foundation Server 2010, and reflects one last change we made to the cube schema from the Release Candidate to the final version. This last change was to improve the performance of cube processing, and in particular, processing the Test Result dimension. We were able to significantly improve performance by removing the Area and Iteration Hierarchy attributes from the Test Result dimension.&lt;br /&gt;
&lt;br /&gt;
So if you have any reports that use these hierarchies in the Test Result dimension, you’ll need to update your reports.&lt;br /&gt;
&lt;br /&gt;
Sunder Raman has provided a higher-level overview of this change:&lt;br /&gt;
&lt;a href="http://blogs.msdn.com/sunder/archive/2010/03/03/team-foundation-server-2010-cube-schema-changes-in-rtm.aspx" title="http://blogs.msdn.com/sunder/archive/2010/03/03/team-foundation-server-2010-cube-schema-changes-in-rtm.aspx"&gt;http://blogs.msdn.com/sunder/archive/2010/03/03/team-foundation-server-2010-cube-schema-changes-in-rtm.aspx&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;Area Hierarchy&lt;/h3&gt;You’ll want to use the Area Hierarchy from the Test Case dimension. The idea is that the test case defines the area that is being tested, so this is the appropriate test result to use. Your other option would be to use the Area Hierarchy from the Test Plan dimension. However, we don’t recommend this because test plans can and often do cover multiple areas.&lt;br /&gt;
&lt;br /&gt;
One side effect of this change is that you’ll now see the area for some test results listed as Unknown. This means they don’t have any area, which will be the case when you publish unit test results that aren’t connected to a Test Case. Previously these test results appeared in the root area path for your Team Project, so it’s a minor change. But now you can at least tell which test results were explicitly connected to an area as a result of being run via a Test Case.&lt;br /&gt;
&lt;h3&gt;Iteration Hierarchy&lt;/h3&gt;You’ll want to use the Iteration Hierarchy from the Test Plan dimension. Test Plans are usually tied to a specific iteration. In Agile development, each new iteration introduces new functionality, and therefore a new test plan is required. Test Cases, on the other hand, don’t really live in any one iteration, so it wouldn’t make sense to use the iteration from the test case.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-1344827243793420927?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2010/03/upgrading-team-foundation-server-2008.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-5057264318339222851</guid><pubDate>Thu, 22 Oct 2009 21:16:00 +0000</pubDate><atom:updated>2009-10-22T15:36:51.844-07:00</atom:updated><title>Customizing Report Parameters for Team Foundation Server 2010</title><description>&lt;p&gt;Very often you’ll want to change the default settings for parameters in a report, but Reporting Services doesn’t have a user interface that allows you to select parameters, and then save them for use again. There is a way to customize the set of parameter values without learning how to author reports, but it’s a little involved. In this post, I’ll cover the following:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Changing the default values that are used to render a report&lt;/li&gt;    &lt;li&gt;Creating multiple views on the same report, each with different default parameters&lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;About Report Parameters&lt;/h3&gt;  &lt;p&gt;First a little bit of background on report parameters. Many of the TFS 2010 reports read from the Analysis Services database (or cube) that, by default, is called Tfs_Analysis (it was called TfsWarehouse in previous releases). Since this is a cube, and not a relational warehouse, default parameter values will look a little odd. As an example, this is what the default value might look like when you want to select “Iteration 1” in the iteration parameter:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[Work Item].[Iteration Hierarchy].[Iteration1].&amp;amp;[10]&amp;amp;[11]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Yikes, you say, how are you supposed to figure that out?&lt;/p&gt;  &lt;p&gt;I’m not going to get into the details of why this is so complicated. If you’re interested, I wrote an &lt;a href="http://msdn.microsoft.com/en-us/library/cc487893.aspx"&gt;MSDN article for TFS 2008&lt;/a&gt; that will give you some idea about how this works, although the details have changed since then.&lt;/p&gt;  &lt;p&gt;But there is a tool you can use to get this information: SQL Server Management Studio, which you can install from the SQL Server DVD. Alternatively, you can use a free program called &lt;a href="http://www.mosha.com/msolap/mdxstudio.htm"&gt;MDX Studio&lt;/a&gt;, which is what I’ll use here as an example.&lt;/p&gt;  &lt;h3&gt;Finding the Default Value&lt;/h3&gt;  &lt;p&gt;The first step is to launch &lt;a href="http://www.mosha.com/msolap/mdxstudio.htm"&gt;MDX Studio&lt;/a&gt; and connect to the TFS cube. You might need to find out the server and database from your TFS administrator, and also have them grant you read access (they need to add you to the TfsWarehouseDataReader role).&lt;/p&gt;  &lt;h4&gt;Finding an Iteration Value&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Launch &lt;a href="http://www.mosha.com/msolap/mdxstudio.htm"&gt;MDX Studio&lt;/a&gt;, type the name of the Analysis Services machine into the &lt;strong&gt;Connect to Analysis Services&lt;/strong&gt; dialog box, and then click on the &lt;strong&gt;Connect&lt;/strong&gt; button. You should see a display something like this:      &lt;br /&gt;&lt;a href="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/MDXStudio.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="MDXStudio" border="0" alt="MDXStudio" src="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/MDXStudio_thumb.png" width="580" height="378" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;In the &lt;strong&gt;Metadata&lt;/strong&gt; section, scroll down so you can see Work Item and expand that item.&lt;/li&gt;    &lt;li&gt;Expand the &lt;strong&gt;Work Item.Iteration Hierarchy&lt;/strong&gt; node.&lt;/li&gt;    &lt;li&gt;Expand the &lt;strong&gt;(All)&lt;/strong&gt; and then &lt;strong&gt;All&lt;/strong&gt; nodes, and then the collection node that contains your team project.&lt;/li&gt;    &lt;li&gt;Expand the node that contains your team project. You should see something like this:     &lt;br /&gt;&lt;a href="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/Iteration1.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Iteration1" border="0" alt="Iteration1" src="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/Iteration1_thumb.png" width="259" height="244" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Finally, drag the iteration node (&lt;strong&gt;Iteration 1&lt;/strong&gt; in this example) into the Query area:      &lt;br /&gt;&lt;a href="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/IterationMDX_3.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IterationMDX" border="0" alt="IterationMDX" src="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/IterationMDX_thumb_3.png" width="580" height="167" /&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;You can now copy this “ID” and use it in the following steps.&lt;/p&gt;  &lt;h3&gt;Setting Parameter Defaults&lt;/h3&gt;  &lt;p&gt;You’ll be using Report Manager to make these changes:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Right click on the &lt;strong&gt;Reports&lt;/strong&gt; node of your team project inside Visual Studio and select &lt;strong&gt;Show Report Site…&lt;/strong&gt;:      &lt;br /&gt;&lt;a href="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/ShowReportSite.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ShowReportSite" border="0" alt="ShowReportSite" src="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/ShowReportSite_thumb.png" width="323" height="196" /&gt;&lt;/a&gt;&amp;#160;&lt;/li&gt;    &lt;li&gt;Click on the &lt;strong&gt;Properties &lt;/strong&gt;tab at the top of the report:      &lt;br /&gt;&amp;#160;&lt;a href="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/PropertiesButton.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="PropertiesButton" border="0" alt="PropertiesButton" src="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/PropertiesButton_thumb.png" width="336" height="199" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Click on the &lt;strong&gt;Parameters&lt;/strong&gt; link:      &lt;br /&gt;&lt;a href="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/ParametersLink.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ParametersLink" border="0" alt="ParametersLink" src="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/ParametersLink_thumb.png" width="275" height="123" /&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;At this point you’ll see a list of parameters, which should look something like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/Parameters.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Parameters" border="0" alt="Parameters" src="http://www.socha.com/blogs/john/uploaded_images/CustomizingReportParametersforTeamFounda_BF8D/Parameters_thumb.png" width="580" height="357" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To change the default iteration, for example, you would paste the value you got from the previous step into the text box circled in red above, and then click on the &lt;strong&gt;Apply&lt;/strong&gt; button.&lt;/p&gt;  &lt;h3&gt;Multiple Parameter Settings – Linked Reports&lt;/h3&gt;  &lt;p&gt;There are times where you’ll want to have several versions of the report, each with different parameter values. Reporting Services has a feature called &lt;em&gt;Linked Reports&lt;/em&gt; that allows you to essentially create sets of parameters that will be applied to a single copy of the report, but appear as a new report.&lt;/p&gt;  &lt;p&gt;Here is how you create a linked report:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Click on the &lt;strong&gt;Properties&lt;/strong&gt; tab for the report (just like in the previous section)&lt;/li&gt;    &lt;li&gt;Click on the &lt;strong&gt;Create Linked Report&lt;/strong&gt; button on the &lt;strong&gt;Properties&lt;/strong&gt; page&lt;/li&gt;    &lt;li&gt;Type in the name you want to use for this new linked report, and then click on the &lt;strong&gt;OK&lt;/strong&gt; button&lt;/li&gt;    &lt;li&gt;Click on the &lt;strong&gt;Properties&lt;/strong&gt; tab of this new linked report&lt;/li&gt;    &lt;li&gt;Click on the &lt;strong&gt;Parameters&lt;/strong&gt; link on the left side to customize the parameter values that will be used for the linked report, and click on the &lt;strong&gt;Apply&lt;/strong&gt; button to accept the new default values&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-5057264318339222851?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2009/10/customizing-report-parameters-for-team.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-8177804141017548390</guid><pubDate>Thu, 15 Oct 2009 20:59:00 +0000</pubDate><atom:updated>2009-10-22T11:13:46.195-07:00</atom:updated><title>Upgrading Team Foundation Server 2008 Reports to 2010, Part II</title><description>&lt;p&gt;My previous post, &lt;a href="http://www.socha.com/blogs/john/2009/05/upgrading-visual-studio-team-foundation.html"&gt;Upgrading Team Foundation Server 2008 Reports to 2010&lt;/a&gt;, provides a lot of information on how to upgrade reports to work with the new 2010 version of Team Foundation Server, and even though I wrote it for Beta 1, much of the information still stands. There are, however, changes that have been made since then, so in this post I’ll provide updated information that applies to &lt;a href="http://blogs.msdn.com/allclark/archive/2009/10/13/enabling-new-application-lifecycle-management-features-for-visual-studio-2010-beta-2-in-upgraded-team-projects.aspx"&gt;Beta 2&lt;/a&gt; (and hopefully the final version of 2010).&lt;/p&gt;  &lt;h3&gt;Cube Changes&lt;/h3&gt;  &lt;p&gt;There were a few breaking changes to the cube that affected our reports, which are described in the sections below. You can find more details on cube changes in Sunder’s blog post: &lt;a href="http://blogs.msdn.com/sunder/archive/2009/10/19/team-foundation-server-2010-cube-schema-changes-in-beta-2.aspx"&gt;Team Foundation Server 2010 - Relational Warehouse and Cube Schema Changes&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;Measure Changes&lt;/h4&gt;  &lt;p&gt;In previous versions of the cube, there were two measure groups for work items: &lt;strong&gt;Work Item History&lt;/strong&gt; and &lt;strong&gt;Current Work Item&lt;/strong&gt;. Here is one example of a measure pair from those two groups:&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;pre id="codeSnippet" class="csharpcode"&gt;[Measures].[Cumulative Count]
[Measures].[Current Work Item Count]&lt;/pre&gt;
Having two measures was always a little confusing. Starting in Beta 2, there is just one measure and one measure group. The measure group is now called &lt;strong&gt;Work Item&lt;/strong&gt;, and there is a single measure that is used for both current and historical:&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;[Measures].[Work Item Count]&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Now this measure will show historical information if you have the Date dimension included in your query, otherwise it will show current information. Much simpler. The other work item measures also follow this new pattern, with a single rather than a pair of measures for each of the work item measures.&lt;/p&gt;

&lt;p&gt;In general, any measure that had &lt;strong&gt;Cumulative&lt;/strong&gt; at the start before, just drop the &lt;strong&gt;Cumulative&lt;/strong&gt;. Likewise, if it had &lt;strong&gt;Current&lt;/strong&gt; at the start of the name, just drop &lt;strong&gt;Current&lt;/strong&gt;. The Count measure above is, of course, an exception. Here is another example of before and after:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;&lt;strong&gt;Before:&lt;/strong&gt; [Measures].[Cumulative Completed Work]
&lt;strong&gt;After:&lt;/strong&gt;  [Measures].[Completed Work]&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;That being said, there are some cases where measures with &lt;strong&gt;Cumulative&lt;/strong&gt; at the start now have &lt;strong&gt;Trend&lt;/strong&gt; at the end of the name. For example, [Measures].[Result Count Trend]. In general, your best bet is to look at the cube and see what the measures are called now.&lt;/p&gt;

&lt;h4&gt;Area/Iteration Hierarchies&lt;/h4&gt;

&lt;p&gt;As I mentioned in the previous post, 2010 introduces team project collections (TPCs), which is a grouping of a set of team projects. Although TPCs were supported in beta 1, the TPC was not included in the area and iteration hierarchies. So if you had two projects with the same name, but in different TPCs, you couldn’t tell which areas/iterations belonged to a specific project.&lt;/p&gt;

&lt;p&gt;To fix this, we added the TPC name as part of the area/iteration hierarchy between the root and the top-level node for the team project. As a result, we had to change all the queries that we use to get the area and iteration parameters.&lt;/p&gt;

&lt;p&gt;In this process of doing this, however, we also realized we could switch to a single query for each parameter instead of the two queries we had before. These new queries look a lot more complicated, but they’re actually not that bad. A bit of of explanation is in order because we also change the default value that we’re using so we can hard-code it rather than using a query. Doing this allowed us to provide a better experience when the cube doesn’t contain any areas or iterations for the team project, which will happen, for example, with a new team project that has no work items.&lt;/p&gt;

&lt;p&gt;Here are the new default values:&lt;/p&gt;

&lt;table style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none; mso-border-alt: solid #4f81bd 1.0pt; mso-border-themecolor: accent1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class="LightList-Accent11" border="1" cellspacing="0" cellpadding="0" width="352"&gt;&lt;tbody&gt;
    &lt;tr style="mso-yfti-irow: -1; mso-yfti-firstrow: yes"&gt;
      &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-left-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="152"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 5" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;Parameter&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1; mso-border-right-themecolor: accent1" valign="top" width="198"&gt;&lt;strong&gt;&lt;font color="#ffffff"&gt;Default Value&lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="mso-yfti-irow: 0"&gt;
      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="152"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;&lt;b&gt;AreaParam&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="198"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;[Work Item].[Area Hierarchy].[All]&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes"&gt;
      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="152"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 4" class="MsoNormal"&gt;&lt;b&gt;IterationParam&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="198"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;[Work Item].[Iteration Hierarchy].[All]&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&amp;#160; &lt;br /&gt;What we’re trying to do is return query results that look something like this:&lt;/p&gt;

&lt;table style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none; mso-border-alt: solid #4f81bd 1.0pt; mso-border-themecolor: accent1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class="LightList-Accent11" border="1" cellspacing="0" cellpadding="0" width="403"&gt;&lt;tbody&gt;
    &lt;tr style="mso-yfti-irow: -1; mso-yfti-firstrow: yes"&gt;
      &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-left-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="152"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 5" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;ParameterCaption&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1; mso-border-right-themecolor: accent1" valign="top" width="249"&gt;&lt;strong&gt;&lt;font color="#ffffff"&gt;ParameterValue&lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="mso-yfti-irow: 0"&gt;
      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="152"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;All (No Filter)&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="249"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;[Work Item].[Area Hierarchy].[All]&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes"&gt;
      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="152"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 4" class="MsoNormal"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;(ProcessTest)&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="249"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;[Work Item].[Area Hierarchy].&amp;amp;[67]&amp;amp;[67]&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes"&gt;
      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="152"&gt;&amp;#160; Iteration 1&lt;/td&gt;

      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="249"&gt;[Work Item].[Area Hierarchy].&amp;amp;[67]&amp;amp;[78]&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&amp;#160; &lt;br /&gt;So how do we get this? Using a few tricks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The All member is always returned. We use a Union function to ensure that we always return this member. &lt;/li&gt;

  &lt;li&gt;The NonEmpty/CrossJoin near the end of this query returns all the members at the Area1 level and below. Area0 is the level of the team project, and there is a level above this for the TPC. By going directly to Area1 and all children of that level, we’re getting all the children of the project. We also cross join with the team project to ensure we only get areas for the current team project. &lt;/li&gt;

  &lt;li&gt;The reason for the Except/Extract function is much less obvious, but it has to do with the outer Descendants function. Basically, we want to get all the first children of the project, and then all children of these members. In order for this to work when there are no matches (in which case the NonEmpty returns no members), we Union the results with the All member, but then we need to remove that member and also return only members in the Work Item dimension. That is what the combination of Extract and then Except accomplishes. &lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;dsArea&lt;/h5&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt;
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[Add Spaces] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        VBA.Space(([Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;span class="kwrd"&gt;Level&lt;/span&gt;.&lt;font color="#800000"&gt;Ordinal&lt;/font&gt; - 1) * 2)
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[ParameterCaption] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        IIF([Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;
               &lt;span class="kwrd"&gt;IS&lt;/span&gt; [Work Item].[Area Hierarchy].[All],
            @AllNoFilter,
            [Measures].[Add Spaces]
                + [Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;Member_Caption&lt;/font&gt;
        )
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[ParameterValue]
        &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;UniqueName&lt;/font&gt;
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[ParameterLevel]
        &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;span class="kwrd"&gt;Level&lt;/span&gt;.&lt;font color="#800000"&gt;Ordinal&lt;/font&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;
{
    [Measures].[ParameterCaption],
    [Measures].[ParameterValue],
    [Measures].[ParameterLevel]
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; COLUMNS,
{
    &lt;span class="kwrd"&gt;Union&lt;/span&gt;(
        [Work Item].[Area Hierarchy].[All],
        &lt;span class="kwrd"&gt;Descendants&lt;/span&gt;(
            &lt;span class="rem"&gt;//&lt;/span&gt;
            &lt;span class="rem"&gt;// We use Except to remove the extra [All] member so we get the descendants
            // only of the&lt;/span&gt;&lt;span class="rem"&gt; team project.&lt;/span&gt;
            &lt;span class="rem"&gt;//&lt;/span&gt;
            &lt;font color="#800000"&gt;Except&lt;/font&gt;(
                &lt;font color="#800000"&gt;Extract&lt;/font&gt;(
                    &lt;span class="kwrd"&gt;Union&lt;/span&gt;(
                        &lt;span class="rem"&gt;//&lt;/span&gt;
                        &lt;span class="rem"&gt;// We add [All] so Extract always has at least one tuple to
                        // work with. Otherwise&lt;/span&gt;&lt;span class="rem"&gt; it produces an error when there are no
                        // tuples returned by the NonEmpty below.&lt;/span&gt;
                        &lt;span class="rem"&gt;//&lt;/span&gt;
                        &lt;font color="#800000"&gt;CrossJoin&lt;/font&gt;(
                            [Team Project].[Project Node GUID].[All],
                            [Work Item].[Area Hierarchy].[All]
                        ),
                        &lt;font color="#800000"&gt;NonEmpty&lt;/font&gt;(
                            &lt;font color="#800000"&gt;CrossJoin&lt;/font&gt;(
                                &lt;font color="#800000"&gt;StrToMember&lt;/font&gt;(&amp;quot;[Team Project].[Project Node GUID].&amp;amp;[{&amp;quot;
                                    + @ProjectGuid + &amp;quot;}]&amp;quot;),
                                [Work Item].[Area Hierarchy].[Area1]
                            ),
                            [Measures].[Work Item Count]
                        )
                    ),
                    [Work Item].[Area Hierarchy]
                ),
                [Work Item].[Area Hierarchy].[All]
            )
        )
    )
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; &lt;span class="kwrd"&gt;ROWS&lt;/span&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;/pre&gt;
&lt;/div&gt;

&lt;h5&gt;dsIteration&lt;/h5&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt;
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[Add Spaces] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        VBA.Space(([Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;span class="kwrd"&gt;Level&lt;/span&gt;.&lt;font color="#800000"&gt;Ordinal&lt;/font&gt; - 1) * 2)
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[ParameterCaption] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        IIF([Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;
                &lt;span class="kwrd"&gt;IS&lt;/span&gt; [Work Item].[Iteration Hierarchy].[All],
            @AllNoFilter,
            [Measures].[Add Spaces]
                + [Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;Member_Caption&lt;/font&gt;
        )
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[ParameterValue]
        &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;UniqueName&lt;/font&gt;
    &lt;span class="kwrd"&gt;MEMBER&lt;/span&gt; [Measures].[ParameterLevel]
        &lt;span class="kwrd"&gt;AS&lt;/span&gt; [Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;span class="kwrd"&gt;Level&lt;/span&gt;.&lt;font color="#800000"&gt;Ordinal&lt;/font&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;
{
    [Measures].[ParameterCaption],
    [Measures].[ParameterValue],
    [Measures].[ParameterLevel]
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; COLUMNS,
{
    &lt;span class="kwrd"&gt;Union&lt;/span&gt;(
        [Work Item].[Iteration Hierarchy].[All],
        &lt;span class="kwrd"&gt;Descendants&lt;/span&gt;(
            &lt;span class="rem"&gt;//&lt;/span&gt;
            &lt;span class="rem"&gt;// We use Except to remove the extra [All] member so we get the descendants
            // only of the&lt;/span&gt;&lt;span class="rem"&gt; team project.&lt;/span&gt;
            &lt;span class="rem"&gt;//&lt;/span&gt;
            &lt;font color="#800000"&gt;Except&lt;/font&gt;(
                &lt;font color="#800000"&gt;Extract&lt;/font&gt;(
                    &lt;span class="kwrd"&gt;Union&lt;/span&gt;(
                        &lt;span class="rem"&gt;//&lt;/span&gt;
                        &lt;span class="rem"&gt;// We add [All] so Extract always has at least one tuple to
                        // work with. Otherwise&lt;/span&gt;&lt;span class="rem"&gt; it produces an error when there are no
                        // tuples returned by the NonEmpty below.&lt;/span&gt;
                        &lt;span class="rem"&gt;//&lt;/span&gt;
                        &lt;font color="#800000"&gt;CrossJoin&lt;/font&gt;(
                            [Team Project].[Project Node GUID].[All],
                            [Work Item].[Iteration Hierarchy].[All]
                        ),
                        &lt;font color="#800000"&gt;NonEmpty&lt;/font&gt;(
                            &lt;font color="#800000"&gt;CrossJoin&lt;/font&gt;(
                                &lt;font color="#800000"&gt;StrToMember&lt;/font&gt;(&amp;quot;[Team Project].[Project Node GUID].&amp;amp;[{&amp;quot;
                                    + @ProjectGuid + &amp;quot;}]&amp;quot;),
                                [Work Item].[Iteration Hierarchy].[Iteration1]
                            ),
                            [Measures].[Work Item Count]
                        )
                    ),
                    [Work Item].[Iteration Hierarchy]
                ),
                [Work Item].[Iteration Hierarchy].[All]
            )
        )
    )
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; &lt;span class="kwrd"&gt;ROWS&lt;/span&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;/pre&gt;
&lt;/div&gt;

&lt;h3&gt;Handling the Turkish “I”&lt;/h3&gt;

&lt;p&gt;It turns out that there are several different “i” letters in Turkish, and this creates problems with one of the queries that we had in Beta 1. You’ll need to change &lt;strong&gt;dsProjectGuid&lt;/strong&gt; to use all caps for the GUID in column name: &lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; ProjectNode&lt;font color="#ff0000"&gt;GUID&lt;/font&gt; &lt;span class="kwrd"&gt;FROM&lt;/span&gt; GetProjectNodeInfoFromReportFolder(@ReportPath)&lt;/pre&gt;

&lt;p&gt;This is to match the case of the actual column name as defined in the warehouse.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-8177804141017548390?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2009/10/upgrading-team-foundation-server-2008.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-957590206310366402</guid><pubDate>Tue, 19 May 2009 04:05:00 +0000</pubDate><atom:updated>2009-10-15T14:54:02.901-07:00</atom:updated><title>Upgrading Team Foundation Server 2008 Reports to 2010, Part I</title><description>&lt;p&gt;There have been some major changes in the reporting infrastructure for the forthcoming 2010 release of Team Foundation Server. You can find a blog entry on these changes here, written by the Program Manager on the team that made these changes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Aaron Bjork, a PM on the Process team, has written a high-level blog post here: &lt;a href="http://blogs.msdn.com/aaronbjork/archive/2009/05/18/team-foundation-server-2010-where-are-my-reports.aspx"&gt;Team Foundation Server 2010 - Where Are My Reports?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Sunder Raman, a PM on the reporting infrastructure team has details on the changes here: &lt;a href="http://blogs.msdn.com/sunder/archive/2009/05/16/team-foundation-server-2010-relational-warehouse-and-cube-schema-changes.aspx"&gt;Team Foundation Server 2010 - Relational Warehouse and Cube Schema Changes&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In this blog post I’m going to dive deep into the details on how to modify reports to work with the new schema. But first, some definitions and background.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#000000"&gt;&lt;strong&gt;Update:&lt;/strong&gt; Although I originally wrote this post for Beta 1, most of the information still applies. Some things have changed, and you’ll find the details here: &lt;a href="http://www.socha.com/blogs/john/2009/10/upgrading-team-foundation-server-2008.html"&gt;Upgrading Team Foundation Server 2008 Reports to 2010, Part II&lt;/a&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;Definitions&lt;/h3&gt;  &lt;table style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none; mso-border-alt: solid #4f81bd 1.0pt; mso-border-themecolor: accent1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class="LightList-Accent11" border="1" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;     &lt;tr style="mso-yfti-irow: -1; mso-yfti-firstrow: yes"&gt;       &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-left-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="91"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 5" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;Term&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1; mso-border-right-themecolor: accent1" valign="top" width="547"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 1" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;Description&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="mso-yfti-irow: 0"&gt;       &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="91"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;&lt;b&gt;Dimension&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="547"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;The dimensions in a cube are at the heart of what makes a cube useful for slicing data in many ways. Data values are associated with a set of dimensions, allowing you to show aggregate results sliced using a specific set of dimension values.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="mso-yfti-irow: 1"&gt;       &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1" valign="top" width="91"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 4" class="MsoNormal"&gt;&lt;b&gt;Fact&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1" valign="top" width="547"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;Data that can be associated with multiple dimensions. This data may also be aggregated. Fact tables hold these values.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="mso-yfti-irow: 2"&gt;       &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="91"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;&lt;b&gt;Attribute&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="547"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;Under each dimension you’ll find a set of attributes and possibly hierarchies (area and iteration are a hierarchies). Each attribute is connected to a column in the corresponding dimension table in the warehouse.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes"&gt;       &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.95in; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="91"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 4" class="MsoNormal"&gt;&lt;b&gt;Measure&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.7in; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="547"&gt;         &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;Measures are values that correspond to columns in the corresponding fact table.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;   &lt;br /&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="StarDiagram" border="0" alt="StarDiagram" src="http://www.socha.com/blogs/john/uploaded_images/UpgradingVisualStudioTeamFoundationServe_AD00/StarDiagram_thumb.png" width="586" height="346" /&gt; &lt;/p&gt;  &lt;h3&gt;SQL Server 2008&lt;/h3&gt;  &lt;p&gt;The new version of Team Foundation Server requires SQL Server 2008, which brings a set of changes with it. I wrote a previous blog post on changes that might affect your existing queries:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.socha.com/blogs/john/2009/03/tfs-report-issues-with-sql-server-2008.html"&gt;TFS Report Issues with SQL Server 2008&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;One significant change is the tools you’ll be using. You’ll need to use the 2008 version of Report Designer, which has a number of UI changes that take a little getting used to. In particular, the entire experience with working with queries has changed dramatically. The 2005 version of Report Designer used three tabs for Data, Layout, and Preview:&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="Bids2005Tabs" border="0" alt="Bids2005Tabs" src="http://www.socha.com/blogs/john/uploaded_images/UpgradingVisualStudioTeamFoundationServe_AD00/Bids2005Tabs_thumb.png" width="193" height="28" /&gt; &lt;/p&gt;  &lt;p&gt;The Data tab is now gone in the 2008 Report Designer, and has been replaced with the Report Data docking window:&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="Bids2008ReportData" border="0" alt="Bids2008ReportData" src="http://www.socha.com/blogs/john/uploaded_images/UpgradingVisualStudioTeamFoundationServe_AD00/Bids2008ReportData_thumb.png" width="284" height="175" /&gt; &lt;/p&gt;  &lt;p&gt;You use this new window to edit and create data sources and report parameters. Editing of data sets is now done in a dialog box that you get to by double-clicking on a dataset, such as dsBugCount in the image above.&lt;/p&gt;  &lt;p&gt;Many of the reports shipped with Team Foundation Server use hand-written MDX for their queries (the other reports use hand-written SQL). As such, if you need to change a query, you’ll be editing the actual query code. Double-clicking on a data set will produce the following dialog:&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="DatasetProperties" border="0" alt="DatasetProperties" src="http://www.socha.com/blogs/john/uploaded_images/UpgradingVisualStudioTeamFoundationServe_AD00/DatasetProperties_thumb.png" width="617" height="480" /&gt; &lt;/p&gt;  &lt;p&gt;This dialog box is the new location for working with query parameters, fields, etc. To edit the query, click on the Query Designer button.&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="QueryDesigner" border="0" alt="QueryDesigner" src="http://www.socha.com/blogs/john/uploaded_images/UpgradingVisualStudioTeamFoundationServe_AD00/QueryDesigner_thumb.png" width="617" height="470" /&gt; &lt;/p&gt;  &lt;p&gt;There is a limitation of this query designer that you’ll likely notice right away—whereas MDX in the 2005 Report Designer was formatted with syntax coloring, the new Query Designer has no formatting for queries, making it difficult to edit the queries.&lt;/p&gt;  &lt;p&gt;I’ve found the easiest way for me to edit queries with syntax color support is to use this approach:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Copy the query from the Query section of the Dataset Properties window (which does have correct line breaks). &lt;/li&gt;    &lt;li&gt;Paste the query into a session of SQL Server Management Studio. &lt;/li&gt;    &lt;li&gt;Copy and paste the modified query into the Query Designer dialog box for testing and saving back to the report. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Updating Reports&lt;/h3&gt;  &lt;p&gt;Updating a Team Foundation Server 2008 report to work with the 2010 version requires making a number of changes. The details of these changes are described in the following sections.&lt;/p&gt;  &lt;h4&gt;MDX Changes&lt;/h4&gt;  &lt;p&gt;Here is a brief list for MDX reports against the cube:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Use the new data source names &lt;/li&gt;    &lt;li&gt;Filter on Project GUID. This involves adding some new parameters and a new dataset &lt;/li&gt;    &lt;li&gt;Update/replace queries use for area/iteration parameters &lt;/li&gt;    &lt;li&gt;Replace WHERE clauses with sub-cube expressions &lt;/li&gt;    &lt;li&gt;Rename dimensions/attributes whose names have changed &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;SQL Changes&lt;/h4&gt;  &lt;p&gt;If you’re working with the SQL warehouse, the changes are also significant. Here is a brief overview of the changes you’ll need to make:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Use the new data source names &lt;/li&gt;    &lt;li&gt;Filter on Project GUID &lt;/li&gt;    &lt;li&gt;Use the new public views when possible &lt;/li&gt;    &lt;li&gt;Make sure your joins use unique keys. For example, work item IDs are no longer unique within the warehouse &lt;/li&gt;    &lt;li&gt;Rename all table references because all table names have changed &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Data Source Rename&lt;/h3&gt;  &lt;p&gt;You’ll find that the names of the Reporting Services data sources used by reports have changed:&lt;/p&gt;  &lt;p&gt;   &lt;table style="border-bottom: medium none; border-left: medium none; width: 3.95in; border-collapse: collapse; margin-left: 0.5in; border-top: medium none; border-right: medium none; mso-border-alt: solid #4f81bd 1.0pt; mso-border-themecolor: accent1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class="LightList-Accent11" border="1" cellspacing="0" cellpadding="0" width="379"&gt;&lt;tbody&gt;       &lt;tr style="mso-yfti-irow: -1; mso-yfti-firstrow: yes"&gt;         &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 135.9pt; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-left-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="181"&gt;           &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 5" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;2008 Name&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;         &lt;/td&gt;          &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 148.5pt; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1; mso-border-right-themecolor: accent1" valign="top" width="198"&gt;           &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 1" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;2010 Name&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;         &lt;/td&gt;       &lt;/tr&gt;        &lt;tr style="mso-yfti-irow: 0"&gt;         &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 135.9pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="181"&gt;           &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;&lt;b&gt;TfsReportsDS&lt;/b&gt;&lt;/p&gt;         &lt;/td&gt;          &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 148.5pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="198"&gt;           &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;Tfs2010ReportsDS&lt;/p&gt;         &lt;/td&gt;       &lt;/tr&gt;        &lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes"&gt;         &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 135.9pt; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="181"&gt;           &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 4" class="MsoNormal"&gt;&lt;b&gt;TfsOlapReportsDS&lt;/b&gt;&lt;/p&gt;         &lt;/td&gt;          &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 148.5pt; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="198"&gt;           &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;Tfs2010OlapReportsDS&lt;/p&gt;         &lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/p&gt;  &lt;p&gt;The new names exist to accommodate upgrading a server where you have an existing set of reports designed for Team Foundation Server 2005 or 2008. Installing the new version creates a new warehouse and cube that use a different, incompatible schema. The new data sources point to the new warehouse and cube, without overwriting the previous data sources. &lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="ServerUpgrade" border="0" alt="ServerUpgrade" src="http://www.socha.com/blogs/john/uploaded_images/UpgradingVisualStudioTeamFoundationServe_AD00/ServerUpgrade_thumb.png" width="477" height="237" /&gt;&lt;/p&gt;  &lt;p&gt;The old warehouse and cube are not removed or overwritten when you upgrade the server so that old reports will continue to work. However, no new data will be added to the pre-upgrade warehouse and cube. Using new data source names allows the old reports, which use the old data sources, to continue to render pre-upgrade data.&lt;/p&gt;  &lt;p&gt;You’ll need to make sure reports that you upgrade use the new data source names so they’ll connect to the new cube. &lt;/p&gt;  &lt;h3&gt;Reports Location&lt;/h3&gt;  &lt;p&gt;The support for Team Project collections in Team Foundation Server 2010 required some changes to the default location of reports. There were two features driving this change:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;There is now a hierarchy instead of a flat list. For example, you can have a Team Project collection that has some projects under it. &lt;/li&gt;    &lt;li&gt;Team Project names are not server-unique as they were in 2008. A project name has to be unique only within a single collection. In other words, the same project name can exist in two different team project collections. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Because of these changes, reports have a different location on the Reporting Services server. The pattern looks like this:&lt;/p&gt;  &lt;p&gt;/TfsReports/Collection0/MyProject&lt;/p&gt;  &lt;p&gt;That also means you need to use a different mechanism to obtain the default project associated with a report. In previous version, you could get the default project name from the report’s path and just use that to filter query results.&lt;/p&gt;  &lt;p&gt;But with team project collections and 2010, you need to use the project’s GUID instead of the name as a filter since the name by itself may not be unique.&lt;/p&gt;  &lt;p&gt;In the warehouse you’ll find a stored procedure you can use to obtain the project’ GUID from the report path, using code like this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Create a parameter called &lt;b&gt;ReportPath&lt;/b&gt; and move it so it’s the second parameter, after &lt;b&gt;ExplicitProject&lt;/b&gt;. &lt;/li&gt;    &lt;li&gt;Add this expression as the default value for the &lt;b&gt;ReportPath&lt;/b&gt; parameter:       &lt;pre class="csharpcode"&gt;=IIF(LEN(Globals!ReportFolder) &amp;gt; 0,
    Globals!ReportFolder,
&lt;span class="kwrd"&gt;    Parameters&lt;/span&gt;!ExplicitProject.&lt;span class="kwrd"&gt;Value&lt;/span&gt;
)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Create a SQL dataset called &lt;b&gt;dsProjectGuid&lt;/b&gt; that has this query: 

    &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; ProjectNodeGuid &lt;span class="kwrd"&gt;FROM&lt;/span&gt; GetProjectNodeInfoFromReportFolder(@ReportPath)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Create a parameter called &lt;b&gt;ProjectGuid&lt;/b&gt; just after the &lt;b&gt;ReportPath&lt;/b&gt; parameter and set the default value to results of the &lt;b&gt;dsProjectGuid&lt;/b&gt; dataset. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will then need to modify your other queries to use the resulting GUID, which is covered below under Cube Improvements.&lt;/p&gt;

&lt;h3&gt;Warehouse Improvements&lt;/h3&gt;

&lt;p&gt;For the first time, writing reports against the warehouse using SQL is officially supported. As a rule of thumb, you’ll generally want to use the cube for historical reports, or reports that require a lot of slicing and dicing using parameters of aggregate data. The cube is really good at this sort of work.&lt;/p&gt;

&lt;p&gt;The warehouse, on the other hand, allows you to create reports that pull loosely related data together in ways not possible with the cube.&lt;/p&gt;

&lt;h4&gt;Views&lt;/h4&gt;

&lt;p&gt;There are now a number of public views to help you work with the warehouse. All of these public views have names that end with “View,” such as WorkItemHistoryView.&lt;/p&gt;

&lt;p&gt;Views that begin with “v” and end with “Overlay” are used for processing the cube, and as such aren’t really meant for use in your reports.&lt;/p&gt;

&lt;h4&gt;Compensating Records&lt;/h4&gt;

&lt;p&gt;When you work with historical data in the warehouse, you’ll need to be aware of compensating records. You’ll find compensating records in tables/views that include historical information, such as WorkItemHistoryView. Whenever you modify a work item, a pair of records is added to the warehouse. One record “undoes” the most recent previous record, and the next record adds the new settings for that work item. The compensating records allow you use to aggregate functions like SUM in query results.&lt;/p&gt;

&lt;p&gt;Also connected with compensating records are two columns: System_ChangedDate and System_RevisedDate. The first column, System_ChangedDate indicates when the change to the work item was made. The other date tells you when the work item was next changed. As an example, suppose that you created a new task at 10:53 on 5/15/2009, and then you modified that work item at 11:23 on the next day. You would then see records like this: 
  &lt;br /&gt;

  &lt;br /&gt;

  &lt;table style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none; mso-border-alt: solid #4f81bd 1.0pt; mso-border-themecolor: accent1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class="LightList-Accent11" border="1" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;
      &lt;tr style="mso-yfti-irow: -1; mso-yfti-firstrow: yes"&gt;
        &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 137.4pt; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-left-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="183"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 5" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;System_ChangedDate&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 135.45pt; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="181"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 1" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;System_RevisedDate&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 113.95pt; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="152"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 1" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;Remaining Work&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 92pt; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1; mso-border-right-themecolor: accent1" valign="top" width="123"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 1" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;RecordCount&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
        &lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr style="mso-yfti-irow: 0"&gt;
        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 137.4pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="183"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;&lt;b&gt;10:53 5/15/2009&lt;/b&gt;&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 135.45pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="181"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;11:23 5/16/2009&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 113.95pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="152"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;20&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 92pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="123"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;1&lt;/p&gt;
        &lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr style="mso-yfti-irow: 1"&gt;
        &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 137.4pt; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1" valign="top" width="183"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 4" class="MsoNormal"&gt;&lt;b&gt;10:53 5/15/2009&lt;/b&gt;&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 135.45pt; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in" valign="top" width="181"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;11:23 5/16/2009&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 113.95pt; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in" valign="top" width="152"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;-20&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 92pt; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1" valign="top" width="123"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;-1&lt;/p&gt;
        &lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr style="mso-yfti-irow: 2; mso-yfti-lastrow: yes"&gt;
        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 137.4pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="183"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;&lt;b&gt;11:23 5/16/2009&lt;/b&gt;&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 135.45pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="181"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;0:00 1/1/9999&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 113.95pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="152"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;10&lt;/p&gt;
        &lt;/td&gt;

        &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 92pt; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="123"&gt;
          &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;1&lt;/p&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;The first record was the original record, and you can see that it was revised at 11:23. The next record “cancels out” the first record, and was added at the same time as the third record. Finally, the third record is the current record, as indicated by the System_RevisedDate set to the maximum value for a DATETIME column. As a result, you can write a query that will return the current remaining work correctly like this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;SUM&lt;/span&gt;(Microsoft_VSTS_Scheduling_RemainingWork)
  &lt;span class="kwrd"&gt;FROM&lt;/span&gt; WorkItemHistoryView &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; System_Id = 108
   &lt;span class="kwrd"&gt;AND&lt;/span&gt; ProjectNodeGUID = &lt;span class="str"&gt;'A8657108-E085-4DE5-B14C-97DAA378D46E'&lt;/span&gt;&lt;/pre&gt;

&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
  &lt;div id="codeSnippetWrapper"&gt;That being said, you’ll get better performance if you use an “As Of” query instead of using SUM.&lt;/div&gt;
&lt;/div&gt;

&lt;h5&gt;As Of Queries&lt;/h5&gt;

&lt;p&gt;The query above returns the “current” results. But what if you want to obtain the results as of a specific day? Let’s say you want to find out the remaining work as of the end of 5/15/2009. Looking at the end of a given day will give you the same results as you’ll get from the cube. Here is what that query will return the remaining work as of the end of 5/16/2009:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; System_Id, Microsoft_VSTS_Scheduling_RemainingWork
  &lt;span class="kwrd"&gt;FROM&lt;/span&gt; WorkItemHistoryView &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; System_ChangedDate &amp;lt; &lt;span class="str"&gt;'5/16/2009'&lt;/span&gt;
   &lt;span class="kwrd"&gt;AND&lt;/span&gt; System_RevisedDate &amp;gt;= &lt;span class="str"&gt;'5/16/2009'&lt;/span&gt;
   &lt;span class="kwrd"&gt;AND&lt;/span&gt; RecordCount &amp;gt; 0
   &lt;span class="kwrd"&gt;AND&lt;/span&gt; ProjectNodeGUID = &lt;span class="str"&gt;'A8657108-E085-4DE5-B14C-97DAA378D46E'&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Here’s how this works. We want to return only the last records for each work item that was modified before 5/16/2009. The System_RevisedDate clause ensures we retrieve only the last record that was modified before 5/16/2009 because it finds the one record that was both modified before and revised after this date (or not revised at all, in which case the date is in the year 9999).&lt;/p&gt;

&lt;p&gt;Additionally, you’ll notice this query tests for a positive RecordCount. Compensating records that cancel out a previous record always have a RecordCount of -1. &lt;/p&gt;

&lt;h4&gt;Uniqueness of ID Values&lt;/h4&gt;

&lt;p&gt;One new feature of Team Foundation Server 2010 is the support for team project collections, which is a group of team projects. Entire team project collections can be moved from one server to another. As a result, the IDs of work items are unique only within a single team project collection, but they may not be unique on a server that contains records from more than one team project collection. That is why the query in the previous section includes a filter on the project GUID in addition to the work item ID.&lt;/p&gt;

&lt;h4&gt;Table Names&lt;/h4&gt;

&lt;p&gt;Most table names have been changed in Team Foundation Server 2010. In previous versions, many of the table names had space in them, which created problems with some reporting tools. In the new warehouse, names do not have spaces, and they also have a prefix to indicate their use: &lt;/p&gt;

&lt;table style="border-bottom: medium none; border-left: medium none; border-collapse: collapse; border-top: medium none; border-right: medium none; mso-border-alt: solid #4f81bd 1.0pt; mso-border-themecolor: accent1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class="LightList-Accent11" border="1" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;
    &lt;tr style="mso-yfti-irow: -1; mso-yfti-firstrow: yes"&gt;
      &lt;td style="border-bottom: medium none; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.7in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-top-themecolor: accent1; mso-border-left-themecolor: accent1; mso-background-themecolor: accent1" valign="top" width="67"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 5" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;Prefix&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: medium none; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.75in; padding-right: 5.4pt; background: #4f81bd; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-top-themecolor: accent1; mso-background-themecolor: accent1; mso-border-right-themecolor: accent1" valign="top" width="552"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 1" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="color: white; mso-themecolor: background1"&gt;Description&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="mso-yfti-irow: 0"&gt;
      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.7in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: medium none; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="67"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 68" class="MsoNormal"&gt;&lt;b&gt;Dim&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.75in; padding-right: 5.4pt; border-top: #4f81bd 1pt solid; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-themecolor: accent1" valign="top" width="552"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 64" class="MsoNormal"&gt;The table contains dimension data, which means the data will appear in the dimensions part of the cube. There is usually one column for each attribute or hierarchy that belongs to the dimension.&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes"&gt;
      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: #4f81bd 1pt solid; padding-bottom: 0in; padding-left: 5.4pt; width: 0.7in; padding-right: 5.4pt; border-top: medium none; border-right: medium none; padding-top: 0in; mso-border-left-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="67"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt; mso-yfti-cnfc: 4" class="MsoNormal"&gt;&lt;b&gt;Fact&lt;/b&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td style="border-bottom: #4f81bd 1pt solid; border-left: medium none; padding-bottom: 0in; padding-left: 5.4pt; width: 5.75in; padding-right: 5.4pt; border-top: medium none; border-right: #4f81bd 1pt solid; padding-top: 0in; mso-border-right-themecolor: accent1; mso-border-bottom-themecolor: accent1" valign="top" width="552"&gt;
        &lt;p style="line-height: normal; margin-bottom: 0pt" class="MsoNormal"&gt;The values of cells in the cube, which show up via measures. Fact tables have foreign keys to various dimension tables.&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
  &lt;br /&gt;As an example, the FactWorkItemHistory table contains a column called StateChangeCount that appears in the cube under measures, in the Work Item History measure folder.&lt;/p&gt;

&lt;p&gt;Additionally, the DimWorkItem table shows up in the dimension hierarchy under Work Item.&lt;/p&gt;

&lt;p&gt;Renaming the tables this way makes it easier to see the connection between tables in the warehouse and their corresponding entities in the cube. &lt;/p&gt;

&lt;h3&gt;Cube Improvements&lt;/h3&gt;

&lt;p&gt;The team working on the warehouse and cube had several goals when they set out to change the cube design:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Make the cube more usable &lt;/li&gt;

  &lt;li&gt;Increase query performance &lt;/li&gt;

  &lt;li&gt;Improve translation and load performance &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Previous versions of the cube had a lot of dimensions, a little over 60. The new cube has been restructured to use less than half the number of dimensions. Yet at the same time, there are more ways to slice than before. This “simplification” was achieved by changing what were dimensions in the old version to attributes on closely related dimensions in the new version. For example, the Activated Date dimension became the Activated Date attribute inside the Work Item dimension.&lt;/p&gt;

&lt;p&gt;Additionally, because the number of attributes on a dimension can be quite high now, many of the attributes are grouped into attribute folders.&lt;/p&gt;

&lt;h4&gt;Area and Iteration&lt;/h4&gt;

&lt;p&gt;Area and iteration used to be dimensions. Now, however, you’ll find area and iteration hierarchies within other dimensions, such as Work Item and Test Result. You’ll need to use the appropriate hierarchy in your query. For example if you’re slicing on test results, you’ll need to use the area/iteration hierarchies within the Test Result dimension.&lt;/p&gt;

&lt;p&gt;Because areas and iterations were changed to become attributes and the project name is no longer unique, the queries for the area and iteration parameters are very different from before.&lt;/p&gt;

&lt;h3&gt;New Parameter Queries&lt;/h3&gt;

&lt;p&gt;If your report has parameters for area and iteration, you’ll need to modify or replace your queries to use the new structure. In this section you’ll find queries we’ve created for area and iteration lists and default values.&lt;/p&gt;

&lt;p&gt;The old structure used a parent/child hierarchy that allowed you to use the project name as a key, making it easy to get the list of available areas and iterations for a team project, as well as the default values.&lt;/p&gt;

&lt;p&gt;In the new structure, team project names are not guaranteed to be unique, so using the project name as a key might give you results for more than one team project. Additionally, the hierarchy is now a natural hierarchy rather than a parent-child hierarchy, which means that you don’t have data members that represent a node without children. Instead, the new hierarchies have the equivalent built into the hierarchy so the queries don’t need to check for DATAMEMBER values and format them differently (by enclosing them in parenthesis).&lt;/p&gt;

&lt;p&gt;The queries to get the default area/iteration return a single member based on the project GUID by looking only at the direct children of the root. Limiting the scope to just the children of the root keeps the query fast.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;font color="#000000"&gt;&lt;strong&gt;Update:&lt;/strong&gt; The queries for area and iteration no longer work in Beta 2 or later. For more information, see &lt;a href="http://www.socha.com/blogs/john/2009/10/upgrading-team-foundation-server-2008.html"&gt;Upgrading Team Foundation Server 2008 Reports to 2010, Part II&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5&gt;dsAreaDefault&lt;/h5&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt;
    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[ParameterCaption] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;Member_Caption&lt;/font&gt;
    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[ParameterValue] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;UniqueName&lt;/font&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;
{
     [Measures].[ParameterCaption],
     [Measures].[ParameterValue]} &lt;span class="kwrd"&gt;ON&lt;/span&gt; COLUMNS,
{
    &lt;font color="#800000"&gt;NonEmpty&lt;/font&gt;(
        &lt;font color="#800000"&gt;CrossJoin&lt;/font&gt;(
            &lt;font color="#800000"&gt;StrToMember&lt;/font&gt;(&amp;quot;[Team Project].[Project Node GUID].&amp;amp;[{&amp;quot; + @ProjectGuid + &amp;quot;}]&amp;quot;),
            &lt;font color="#0000ff"&gt;Descendants&lt;/font&gt;([Work Item].[Area Hierarchy].[&lt;span class="kwrd"&gt;All&lt;/span&gt;].&lt;font color="#800000"&gt;Children&lt;/font&gt;, 0)
        ),
        [Measures].[Cumulative Count]
    )
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; &lt;span class="kwrd"&gt;ROWS&lt;/span&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;/pre&gt;

&lt;h5&gt;dsArea&lt;/h5&gt;

&lt;p&gt;This data set uses as input the results from the dsAreaDefault query so it will scan only areas in the current project. Limiting the scope to just the children of the default area significantly improves performance of this query.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt;
    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[Add Spaces] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        VBA.&lt;span class="kwrd"&gt;Space&lt;/span&gt;([Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;span class="kwrd"&gt;Level&lt;/span&gt;.&lt;font color="#800000"&gt;Ordinal&lt;/font&gt; * 2)
    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[ParameterCaption] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Measures].[Add Spaces] + [Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;Member_Caption&lt;/font&gt;
    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[ParameterValue] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Work Item].[Area Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;UniqueName&lt;/font&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;
{
     [Measures].[ParameterCaption],
     [Measures].[ParameterValue]} &lt;span class="kwrd"&gt;ON&lt;/span&gt; COLUMNS,
{
    &lt;font color="#0000ff"&gt;Descendants&lt;/font&gt;(&lt;font color="#800000"&gt;StrToSet&lt;/font&gt;(@AreaDefault))
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; &lt;span class="kwrd"&gt;ROWS&lt;/span&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;/pre&gt;

&lt;h5&gt;dsIterationDefault&lt;/h5&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt;
    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[ParameterCaption] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;Member_Caption&lt;/font&gt;&lt;br /&gt;    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[ParameterValue] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;UniqueName&lt;/font&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;
{
     [Measures].[ParameterCaption],
     [Measures].[ParameterValue]} &lt;span class="kwrd"&gt;ON&lt;/span&gt; COLUMNS,
{
    &lt;font color="#800000"&gt;NonEmpty&lt;/font&gt;(
        &lt;font color="#800000"&gt;CrossJoin&lt;/font&gt;(
            &lt;font color="#800000"&gt;StrToMember&lt;/font&gt;(&amp;quot;[Team Project].[Project Node GUID].&amp;amp;[{&amp;quot; + @ProjectGuid + &amp;quot;}]&amp;quot;),
            &lt;font color="#0000ff"&gt;Descendants&lt;/font&gt;([Work Item].[Iteration Hierarchy].[&lt;span class="kwrd"&gt;All&lt;/span&gt;].&lt;font color="#800000"&gt;Children&lt;/font&gt;, 0)
        ),
         [Measures].[Cumulative Count]
    )
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; &lt;span class="kwrd"&gt;ROWS&lt;/span&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;/pre&gt;

&lt;h5&gt;dsIteration&lt;/h5&gt;

&lt;p&gt;This data set uses as input the results from the dsIterationDefault query.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt;
    &lt;font color="#0000ff"&gt;MEMBER&lt;/font&gt; [Measures].[ParameterCaption] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;Member_Caption&lt;/font&gt;
    &lt;font color="#0000ff"&gt;MEMBER &lt;/font&gt;[Measures].[ParameterValue] &lt;span class="kwrd"&gt;AS&lt;/span&gt;
        [Work Item].[Iteration Hierarchy].&lt;font color="#800000"&gt;CurrentMember&lt;/font&gt;.&lt;font color="#0000ff"&gt;UniqueName&lt;/font&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;
{
     [Measures].[ParameterCaption],
     [Measures].[ParameterValue]} &lt;span class="kwrd"&gt;ON&lt;/span&gt; COLUMNS,
{
    NonEmpty(
        CrossJoin(
            &lt;font color="#800000"&gt;StrToMember&lt;/font&gt;(&amp;quot;[Team Project].[Project Node GUID].&amp;amp;[{&amp;quot; + @ProjectGuid + &amp;quot;}]&amp;quot;),
            &lt;font color="#0000ff"&gt;Descendants&lt;/font&gt;([Work Item].[Iteration Hierarchy].[&lt;span class="kwrd"&gt;All&lt;/span&gt;].&lt;font color="#800000"&gt;Children&lt;/font&gt;, 0)
        ),
        [Measures].[Cumulative Count]
    )
} &lt;span class="kwrd"&gt;ON&lt;/span&gt; &lt;span class="kwrd"&gt;ROWS&lt;/span&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;/pre&gt;

&lt;h3&gt;Other Modifications&lt;/h3&gt;

&lt;h4&gt;Project Filter&lt;/h4&gt;

&lt;p&gt;You’ll need to modify all uses of the project name to use the GUID instead. The old version is on the top, and the new version is on the bottom, with the changes highlighted in yellow.&lt;/p&gt;

&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;&lt;font color="#800000"&gt;STRTOMEMBER&lt;/font&gt;(&amp;quot;[Team Project].[Team Project].[&amp;quot; + @Project + &amp;quot;]&amp;quot;),&lt;br /&gt;&lt;font color="#800000"&gt;STRTOMEMBER&lt;/font&gt;(&amp;quot;[Team Project].[&lt;font style="background-color: #ffff00"&gt;Project Node GUID&lt;/font&gt;].[&lt;font style="background-color: #ffff00"&gt;{&lt;/font&gt;&amp;quot; + @Project&lt;font style="background-color: #ffff00"&gt;Guid&lt;/font&gt; + &amp;quot;&lt;font style="background-color: #ffff00"&gt;}&lt;/font&gt;]&amp;quot;),&lt;/pre&gt;
&lt;/div&gt;

&lt;h4&gt;WHERE Clause&lt;/h4&gt;

&lt;p&gt;Many of the reports used the MDX WHERE clause to slice the data on team project, as well as other dimensions. However, this doesn’t always work with SQL Analysis Services 2008 because of changes in how queries are processed. Additionally, it’s not as fast as it could be because the slicing is done &lt;i&gt;after&lt;/i&gt; the query body has been processed.&lt;/p&gt;

&lt;p&gt;A much better approach is to replace the WHERE clause with a sub-cube expression because a sub-cube expression is applied &lt;i&gt;before&lt;/i&gt; processing the rest of the query. Here is the before and after:&lt;/p&gt;

&lt;h5&gt;Before&lt;/h5&gt;

&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;br /&gt;&lt;span class="kwrd"&gt;WHERE&lt;/span&gt;&lt;br /&gt;(&lt;br /&gt;    &lt;font color="#800000"&gt;STRTOMEMBER&lt;/font&gt;(&amp;quot;[Team Project].[Project Node GUID].[{&amp;quot; + @ProjectGuid + &amp;quot;}]&amp;quot;),&lt;br /&gt;    &lt;font color="#800000"&gt;STRTOSET&lt;/font&gt;(@IterationParam),&lt;br /&gt;    &lt;font color="#800000"&gt;STRTOSET&lt;/font&gt;(@AreaParam),&lt;br /&gt;    &lt;font color="#800000"&gt;StrToMember&lt;/font&gt;(&amp;quot;[Work Item].[System_WorkItemType].[&amp;quot; + @Bug + &amp;quot;]&amp;quot;)&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h5&gt;Improved&lt;/h5&gt;

&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;&lt;span class="kwrd"&gt;&lt;font style="background-color: #ffff00"&gt;FROM&lt;/font&gt;&lt;/span&gt;&lt;br /&gt;&lt;font style="background-color: #ffff00"&gt;(&lt;/font&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&lt;font style="background-color: #ffff00"&gt;SELECT&lt;/font&gt;&lt;/span&gt;&lt;br /&gt;    &lt;font style="background-color: #ffff00"&gt;CrossJoin(&lt;/font&gt;&lt;br /&gt;        &lt;font color="#800000"&gt;STRTOMEMBER&lt;/font&gt;(&amp;quot;[Team Project].[Project Node GUID].[{&amp;quot; + @ProjectGuid + &amp;quot;}]&amp;quot;),&lt;br /&gt;        &lt;font color="#800000"&gt;STRTOSET&lt;/font&gt;(@IterationParam),&lt;br /&gt;        &lt;font color="#800000"&gt;STRTOSET&lt;/font&gt;(@AreaParam),&lt;br /&gt;        &lt;font color="#800000"&gt;StrToMember&lt;/font&gt;(&amp;quot;[Work Item].[System_WorkItemType].[&amp;quot; + @Bug + &amp;quot;]&amp;quot;)&lt;br /&gt;    &lt;font style="background-color: #ffff00"&gt;) &lt;span class="kwrd"&gt;ON&lt;/span&gt; COLUMNS&lt;/font&gt;&lt;br /&gt;    &lt;font style="background-color: #ffff00"&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Team System]&lt;/font&gt;&lt;br /&gt;&lt;font style="background-color: #ffff00"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3&gt;Complement Changes&lt;/h3&gt;

&lt;p&gt;Some of the reports used the complement operator (“-“), which performs much the same functionality as the EXCEPT function in MDX. However, these queries used the complement operator inside a WHERE clause in such a way that it produces an error in SQL Analysis Services 2008:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;,&lt;font color="#800000"&gt;STRTOMEMBER&lt;/font&gt;(&amp;quot;[Team Project].[Team Project].[&amp;quot; + @Project + &amp;quot;]&amp;quot;)&lt;br /&gt;,-{&lt;font color="#800000"&gt;STRTOMEMBER&lt;/font&gt;(&amp;quot;[Work Item].[System_State].[System_State].[+@Proposed+]&amp;quot;)}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The problem with this statement is that there is no mention of the Work Item dimension elsewhere inside the WHERE clause. What you need instead is exclude a value from a list of values, like this:&lt;/p&gt;

&lt;div id="codeSnippetWrapper" class="csharpcode-wrapper"&gt;
  &lt;pre id="codeSnippet" class="csharpcode"&gt;&lt;span class="kwrd"&gt;EXCEPT&lt;/span&gt;(&lt;br /&gt;&lt;br /&gt;    &lt;font color="#0000ff"&gt;Descendants&lt;/font&gt;([Work Item].[System_State].[System_State])&lt;br /&gt;    ,&lt;font color="#800000"&gt;STRTOMEMBER&lt;/font&gt;(&amp;quot;[Work Item].[System_State].[System_State].[+@Proposed+]&amp;quot;)&lt;br /&gt;)&lt;/pre&gt;
&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-957590206310366402?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2009/05/upgrading-visual-studio-team-foundation.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-6490193577599892834</guid><pubDate>Tue, 10 Mar 2009 19:36:00 +0000</pubDate><atom:updated>2009-03-10T12:36:48.342-07:00</atom:updated><title>SharePoint Access Denied on SPWebApplication</title><description>&lt;p&gt;I've been working on a SharePoint solution that needed to write properties to the current web application. Everything worked just fine on my development machine. But on some of our test machines, I found the following message in the SharePoint logs:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The SPPersistedObject, SPWebApplication Name=Default Web Site Parent=SPWebService, could not be updated because the current user is not a Farm Administrator. &lt;p&gt;System.Security.SecurityException: Access denied.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This turns out to be correct behavior, but it took a while to understand what was going on and how to setup my development machine to reproduce the problem. &lt;p&gt;In my code to set the web application property value, I was using RunWithElevatedPrivileges to ensure I had rights. However, what I didn't realize is that elevating privileges gives you full access to the content database, &lt;strong&gt;but not&lt;/strong&gt; to the configuration database. SPWebApplication's property bag is stored in the configuration database, not the content database. That was one piece to the puzzle. &lt;p&gt;The other piece to the puzzle was how I had my development machine setup. I was using the same account on both the Central Administration application pool and the application pool used to run regular the web applications. So in essence, I was implicitly granting my code rights to write to the configuration database. &lt;p&gt;When I modified the application pools to use two different accounts, I was able to reproduce this problem on my development machine. &lt;p&gt;Here is a summary: &lt;ul&gt; &lt;li&gt;RunWithElevatedPrivileges only provides full access to the content database for the current web application. In other words, you can modify read-only lists, write SPWeb properties, etc. But you can't make changes to the SPWebApplication because it is persisted to the configuration database.&lt;/li&gt; &lt;li&gt;Always make sure your application pools for normal web applications are using a different account than the Central Administration application pool. This is recommended practice for production machines, but you should also setup your development and test machines this way to catch problems early.&lt;/li&gt;&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-6490193577599892834?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2009/03/sharepoint-access-denied-on.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-4577923792717002354</guid><pubDate>Thu, 05 Mar 2009 21:40:00 +0000</pubDate><atom:updated>2009-03-05T13:40:22.347-08:00</atom:updated><title>TFS Report Issues with SQL Server 2008</title><description>&lt;p&gt;Some of the reports that shipped with Team Foundation Server 2005 and 2008 run into problems when you attempt to run them on SQL Server 2008 Reporting Services. Here is an overview of of the problems and fixes for those problems. Most of these problems are a result of changes in how Analysis Services processes queries in 2008 vs 2005.&lt;/p&gt; &lt;h2&gt;Complement and Except Errors&lt;/h2&gt; &lt;p&gt;Several of the TFS reports show one of these errors when running under SQL 2008:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The set must have a single hierarchy to be used with the complement operator.&lt;/p&gt; &lt;p&gt;Two sets specified in the EXCEPT function have different dimensionality.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The reports that are affected are &lt;strong&gt;Scenario Details&lt;/strong&gt; and &lt;strong&gt;Unplanned Work&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;What does this mean? Basically, it means that the WHERE clause in the query is using the "-" operator to exclude a specific attribute from the query. For example, the Scenario Details reports includes the following inside the WHERE clause:&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;,&lt;span style="color: maroon"&gt;STRTOSET&lt;/span&gt;( @AreaParam )&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;,&lt;span style="color: maroon"&gt;STRTOSET&lt;/span&gt;( @IterationParam )&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;,&lt;span style="color: maroon"&gt;STRTOMEMBER&lt;/span&gt;("[Team Project].[Team Project].[" + @Project + "]")&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;,-{&lt;span style="color: maroon"&gt;STRTOMEMBER&lt;/span&gt;("[Work Item].[System_State].[System_State].[+@Proposed+]")}&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;font size="1"&gt;&lt;/font&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The minus sign in front of the last line indicates that we want to filter out work items that are in the Proposed state. However, this doesn't work in SQL 2008. You'll notice that we're trying to exclude an a specific value without mentioning the other values.&lt;/p&gt; &lt;p&gt;The solution is to remove the exclusion from the WHERE clause and put it into the body of the query:&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;,&lt;span style="color: maroon"&gt;STRTOSET&lt;/span&gt;( @AreaParam )&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;,&lt;span style="color: maroon"&gt;STRTOSET&lt;/span&gt;( @IterationParam )&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;,&lt;span style="color: maroon"&gt;EXCEPT&lt;/span&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;Descendants&lt;/span&gt;([Work Item].[System_State].[System_State])&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;,&lt;span style="color: maroon"&gt;STRTOMEMBER&lt;/span&gt;("[Work Item].[System_State].[System_State].[+@Proposed+]")&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p&gt;The key here is that we need to include all states except for the Proposed state, which is what the Except function above does.&lt;/p&gt; &lt;h2&gt;WHERE vs Sub Cube&lt;/h2&gt; &lt;p&gt;Many of the reports were written using the WHERE clause to filter the results. For example, so the results would be filtered on a single team project instead of the entire cube. However, the behavior of the WHERE clause changed somewhat in SQL Server Analysis Services 2008. The simplest solution is to rewrite the WHERE clause as a sub-cube expression instead. Not only will this fix some of the problems, but it should also make reports run faster.&lt;/p&gt; &lt;h3&gt;Old Version:&lt;/h3&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;FROM&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; [Team System]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;WHERE&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: maroon"&gt;&amp;nbsp; STRTOMEMBER&lt;/span&gt;("[Team Project].[Team Project].[" + @Project + "]"),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: maroon"&gt;&amp;nbsp; STRTOMEMBER&lt;/span&gt;("[Work Item].[System_WorkItemType].[" + @Bug + "]")&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: 'Courier New'; mso-no-proof: yes"&gt;)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;h4&gt;New Version:&lt;/h4&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;FROM&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp; SELECT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: maroon"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CrossJoin&lt;/span&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: maroon"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; STRTOMEMBER&lt;/span&gt;("[Team Project].[Team Project].[" + @Project + "]"),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: maroon"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; STRTOMEMBER&lt;/span&gt;("[Work Item].[System_WorkItemType].[" + @Bug + "]")&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;span style="color: blue"&gt;ON&lt;/span&gt; &lt;span style="color: blue"&gt;COLUMNS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp; FROM&lt;/span&gt; [Team System]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The WHERE clause above is applied after the rest of the MDX expression has been evaluated. But the second expression defines a subset of the cube that will be used to evaluate the rest of the expression. In other words, using a sub cube, you're restricting the set of cells to a smaller set before evaluating the query.&lt;/p&gt; &lt;h2&gt;Extract Problems&lt;/h2&gt; &lt;p&gt;Here is the error message you might see: &lt;blockquote&gt; &lt;p&gt;The Extract function was called with hierarchy 'System_Id' that does not exist in the set. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;That's certainly not a very helpful error message. This message appears in the report called &lt;strong&gt;Bugs Found Without Corresponding Tests&lt;/strong&gt;. The solution, as it turns out, is to use a sub-cube instead of a WHERE clause (described above). &lt;h2&gt;Tuple Problem&lt;/h2&gt; &lt;p&gt;In several of the reports, selecting all of the iterations produces the following error message:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The function expects a tuple expression for the argument. A tuple set expression was used. &lt;p&gt;More than 4,294,967,296 tuples&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This error occurs with the following reports: &lt;ul&gt; &lt;li&gt;Bugs by Priority&lt;/li&gt; &lt;li&gt;Bugs Found Without Corresponding Tests&lt;/li&gt; &lt;li&gt;Issues and Blocked Work Items&lt;/li&gt; &lt;li&gt;Related Work Items&lt;/li&gt; &lt;li&gt;Requirement Details&lt;/li&gt; &lt;li&gt;Requirements Test History and Overview&lt;/li&gt; &lt;li&gt;Scenario Details&lt;/li&gt; &lt;li&gt;Triage&lt;/li&gt; &lt;li&gt;Unplanned Work&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The solution to this problem is also to replace the WHERE clause at the end of the MDX query with a sub-cube expression, as described above. &lt;h2&gt;SQL Reports and the IN Clause&lt;/h2&gt; &lt;p&gt;The &lt;strong&gt;Load Test Summary&lt;/strong&gt; report is a SQL report, and it contains an IN clause in the WHERE statement. This is used to allow multiple values to be selected and passed to the query. However, a change in behavior in SQL 2008 Reporting Services means that you'll see the following message when you have no values: &lt;blockquote&gt; &lt;p&gt;Incorrect syntax near ')'. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Here is why you see this message. The WHERE clause in the &lt;strong&gt;Load Test Summary&lt;/strong&gt; report looks like this: &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; color: blue; line-height: 115%; font-family: 'Courier New'; mso-no-proof: yes"&gt;WHERE &lt;/span&gt;&lt;span style="font-size: 10pt; color: gray; line-height: 115%; font-family: 'Courier New'; mso-no-proof: yes"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: 'Courier New'; mso-no-proof: yes"&gt;Result&lt;span style="color: gray"&gt;.&lt;/span&gt;__ID &lt;span style="color: gray"&gt;IN&lt;/span&gt;&lt;span style="color: blue"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;@ResultParam&lt;span style="color: gray"&gt;))&lt;/span&gt; &lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="color: gray"&gt;AND&lt;/span&gt;&lt;span style="color: blue"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;[Test Result]&lt;span style="color: gray"&gt;.&lt;/span&gt;[Result Record Count] &lt;span style="color: gray"&gt;=&lt;/span&gt; 1&lt;span style="color: gray"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;When there are no results passed into this query, Reporting Services 2008 simply removes @ResultParam, so you get something like "IN ()", and you get a syntax error, preventing this query from running. &lt;p&gt;The solution is to add an expression to the @ResultParam query parameter. This expression is evaluated in order to determine what is passed to the query. Here is what works: &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: 'Courier New'; mso-no-proof: yes"&gt;=IIF(Parameters!ResultParam.Count &amp;gt; 0, Parameters!ResultParam.Value, &lt;span style="color: #a31515"&gt;""&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-4577923792717002354?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2009/03/tfs-report-issues-with-sql-server-2008.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-1250985935223272758</guid><pubDate>Tue, 13 Jan 2009 18:38:00 +0000</pubDate><atom:updated>2009-01-13T10:38:06.180-08:00</atom:updated><title>TF26062 Error for Area and Iteration paths</title><description>&lt;p&gt;This is a post about Microsoft Team Foundation Server and setting the default iteration for new work items, and why it won't work. We recently had a request to modify a User Story work item so that the default iteration would be \Backlog instead of simply \ (the root of the project). The idea is that new stories added to an agile project should be added to the backlog, and then scheduled into a future iteration.&lt;/p&gt; &lt;p&gt;Work items are defined using XML, and each field on a work item form is defined with a FIELD element in this XML. For most fields you can provide a default value that will be filled in when you create a new work item of that type. This is done using code like this:&lt;/p&gt; &lt;p&gt;&amp;lt;FIELD name="Iteration Path" refname="System.IterationPath" type="TreePath"&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DEFAULT from="value" value="$$PROJECTNAME$$\Backlog"/&amp;gt;&lt;br&gt;&amp;lt;/FIELD&amp;gt;&lt;/p&gt; &lt;p&gt;Unfortunately, this doesn't work. If you try to upload a process template that contains a work item type definition with this code, you'll get an error like this one:&lt;/p&gt; &lt;p&gt;Exception Message: TF26062: Rule '&amp;lt;DEFAULT from="value" value="$$PROJECTNAME$$\Backlog" /&amp;gt;' is not supported for the field 'System.IterationPath'.&lt;/p&gt; &lt;p&gt;It turns out the current rules engine for work items doesn't allow setting a default value for either area or iteration when you create a new work item.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-1250985935223272758?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2009/01/tf26062-error-for-area-and-iteration.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-5320214684738842503</guid><pubDate>Tue, 23 Oct 2007 20:35:00 +0000</pubDate><atom:updated>2007-10-23T13:35:35.485-07:00</atom:updated><title>The Abstract Tar Pit</title><description>&lt;p&gt;How often have you found yourself arguing with another person, and they just don't seem to understand you? Chances are they feel that you just don't understand them. You've fallen into the &lt;strong&gt;abstract tar pit&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;Abstract discussions are like abstract art--they can be very appealing, in part because you can interpret the abstract art however you want to. People love to see what they want to see. But when it comes to technical discussions, abstract discussions are dangerous. There is a good chance someone listening to your abstract arguments will understand completely--but it won't be what you're trying to convey. To understand the abstract, they're&amp;nbsp;likely creating concrete examples in their&amp;nbsp;head and then arguing against your ideas based on these "private" concrete examples. The problem is, if these concrete examples aren't shared, you'll get an argument about completely different examples and understandings.&lt;/p&gt; &lt;p&gt;I recently worked on a 5-week project where this was really clear. There&amp;nbsp;was a small group&amp;nbsp;who had an idea they were trying to sell internally to get funding. Everyone else was feeling confused. Just when they thought they understood these ideas, another concept came along that contradicted what they thought they understood.&lt;/p&gt; &lt;p&gt;So we started a project using Expression Blend to create a "movie" of the idea. The first week we brainstormed a lot, and then drew sketches by hand of what the different screens would look like. We then presented these hand-drawn screens to a customer advisory board so we could get their feedback and help us decide what we should focus on during the next week. We intentionally used hand-drawn sketches in our discussions with customers so they wouldn't get bogged down in the small details and would just focus on the big picture.&lt;/p&gt; &lt;p&gt;About half way through the project we started to create actual screen mockups and animate them with Microsoft Expression Blend so it would look like a screen capture movie of an actual program--but it was all smoke and mirrors.&lt;/p&gt; &lt;p&gt;During the project, the team that had come up with the ideas were constantly arguing with us and saying we were asking the wrong questions. But when we had the final "movie" and showed it to them, an interesting thing happened. The conversations changed from being abstract to concrete. The idea team started to explain the details that we got wrong. And in the process, we discovered that we had gotten most of their vision correct--we just differed in some of the details.&lt;/p&gt; &lt;p&gt;What's more, other people who had been confused completely got the idea after seeing the movie. And again, the discussions were at a concrete level, so the discussions that came after seeing the movie were far more productive.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-5320214684738842503?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2007/10/abstract-tar-pit.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-2919629343973157531</guid><pubDate>Fri, 10 Aug 2007 19:10:00 +0000</pubDate><atom:updated>2007-08-10T12:11:29.080-07:00</atom:updated><title>The Stages of Collaboration</title><description>&lt;p&gt;Recently I've been working on an effort to create a new standard for a network protocol in the Model Railroad industry. There are several groups who began work on this effort independently without knowledge of the other groups. As it turns out, there are two groups with similar approaches and we've been trying to work together to create a unified proposal.&lt;/p&gt; &lt;p&gt;During this process, I realized that there are four stages that you must work through before you can come together with a unified approach that is truly a group effort:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Respect:&lt;/strong&gt; First, you have to respect other people's knowledge and abilities. If you don't respect them, you're not going to listen to what they have to say. They also need to respect you, so there needs to be some work up front&amp;nbsp;so each member learns to respect the other team members.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Understanding:&lt;/strong&gt; This is a two way street. You need to make sure you understand what other people are proposing so you can see similarities and differences before you suggest changes. If you see what you believe are holes in another approach, you should ask questions about how they would handle that situation to help you understand. Either you'll help them see the hole, or you'll discover you didn't fully understand their approach. In either case, your questions &lt;strong&gt;&lt;em&gt;must&lt;/em&gt;&lt;/strong&gt; be sincere questions designed to help you understand both the advantages and disadvantages of other approaches.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Trust:&lt;/strong&gt; You have to believe that each person is trying to work together to a common goal without hidden agendas. If you suspect they have a hidden agenda, you haven't achieved mutual trust yet.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Compromise:&lt;/strong&gt; For any group effort to succeed, you must have compromise. But the compromises must come after the understanding and trust have developed or you're just giving in to reach an agreement.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-2919629343973157531?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2007/08/states-of-collaboration.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-2254009379327175488</guid><pubDate>Thu, 19 Jul 2007 18:11:00 +0000</pubDate><atom:updated>2007-07-19T11:11:36.870-07:00</atom:updated><title>Programming is Continuous Brainstorming</title><description>&lt;p&gt;I was talking about pair programming recently with Mike at a company in Everett, WA, and he asked the usual question: "Doesn't having two people working on the same computer mean we lose productivity?" In response, I blurted out a reply: "Imagine that you need to do some brainstorming and you go into a room by yourself." He got the point.&lt;/p&gt; &lt;p&gt;Mike is&amp;nbsp;a business person, not a developer, so I came up with this analogy because I was looking for something that would resonate with a business person. However, while driving home&amp;nbsp;I realized it's actually much more than a simple analogy. Programming is, in fact, continuous brainstorming, which is why two heads are better (and more productive) than one. Or even the same two people working apart.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-2254009379327175488?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2007/07/programming-is-continuous-brainstorming.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-116801806510715423</guid><pubDate>Fri, 05 Jan 2007 17:27:00 +0000</pubDate><atom:updated>2007-01-05T09:27:45.180-08:00</atom:updated><title>Users are Idiomatic</title><description>&lt;p&gt;I recently&amp;nbsp;had&amp;nbsp;a discussion with &lt;a href="http://blogs.msdn.com/jmeier/default.aspx"&gt;J.D. Meier&lt;/a&gt; about user interfaces. During that discussion, I was talking about how users aren't consistent in a way that programs would define consistency. I've been having this discussion for years because of lessons I learned while writing the Norton Commander. Back then I discovered that in order to make an application "feel" consistent, the code need to include many special cases. But I've never had a succinct way to describe this.&lt;/p&gt; &lt;p&gt;But during my discussion with J.D. yesterday, he mentioned idioms and models and I realized that that's really the issues. Model-based design uses models to help create the design, and that's useful for many things. However, users, by nature, are not model driven--&lt;em&gt;users are idiomatic&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;One of the definitions of idiomatic, from the &lt;a href="http://www.m-w.com/dictionary/idiomatic"&gt;Merriam-Webster&lt;/a&gt; dictionary is this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#000000"&gt;"peculiar to a particular group, individual, or style"&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;There are actually several aspects to viewing users as idiomatic.&lt;/p&gt; &lt;p&gt;First, different users will have different definitions of "intuitive." So when designing software, you need identify the different groups to understand what they're expected. But to make it even more interesting, individuals tend to jump from one group to another&amp;nbsp;on a whim, so this process is by no means an easy process.&lt;/p&gt; &lt;p&gt;Second, and this isn't conveyed directly by the definition of idiomatic, users actually expect inconsistent behavior. Let me say that again. &lt;em&gt;Users expect inconsistent behavior.&lt;/em&gt; What I mean by this is that&amp;nbsp;code that "feels" correct to users&amp;nbsp;typically has lots of special-case code to make the interface feel natural. As an example, going way back to the mid 1980s with the Norton Commander, I had scroll bars for a file viewer. In these days the thumb of the scroll bar moved by an entire line at a time and only had 23 possible positions. The usual approach for positioning the thumb is to calculate the percentage into the file and use this for the thumb position.&lt;/p&gt; &lt;p&gt;But imagine for a moment what happens when you have a long document. You page down several times and the thumb hasn't moved at all. Makes sense, right? You're probably thinking about the math when you answered that question. However users for the most part aren't familiar with the principles that lead to the code that controls the thumbs position. Instead, they're probably expecting the thumb to&amp;nbsp;give them some indication of where they are in the file. One common reaction was that they must be at the top of the file because the thumb is at the very top.&lt;/p&gt; &lt;p&gt;So what I did was add some special case code that would move the thumb away from the top the minute you scrolled away from the top-most line of the file. Likewise, the thumb would not be at the very bottom until the last line in the file was visible. In between these two positions the thumb position was proportional.&lt;/p&gt; &lt;p&gt;This type of special-case code is what makes a program "feel" right to a user, but it often drives programmers nuts. My libraries were used by the people who wrote Norton Utilities 5.0. One of the first things they did when they started to change these libraries is to remove these special cases because they were "confusing" to users. The actual fact is that they were inconsistent &lt;em&gt;by design&lt;/em&gt;. The inconsistency was in&amp;nbsp;understanding that users views and "models"&amp;nbsp;often do not map well into logical models because users are idiomatic.&amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-116801806510715423?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2007/01/users-are-idiomatic.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-116594965236854872</guid><pubDate>Tue, 12 Dec 2006 18:54:00 +0000</pubDate><atom:updated>2006-12-12T10:54:12.450-08:00</atom:updated><title>Customizing TFS Work Item States and Reporting</title><description>&lt;p&gt;We're using Team Foundation Server to manage our projects. The MSF Agile template, which is what we started with, has just two states for Tasks: Active and Closed. We wanted to add more states to keep track of the flow through iteration planning and test, so we ended up with the following states:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#000000"&gt;Pending&lt;br&gt;In Process&lt;br&gt;Developed&lt;br&gt;In Test&lt;br&gt;Closed&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The initial state of Pending means it hasn't been planned for an iteration, whereas In Process means it's been assigned to an iteration. You could certainly envision other states, but you probably get the idea.&lt;/p&gt; &lt;p&gt;I added new states and transitions to the template and uploaded&amp;nbsp;it to the server (you can use &lt;a href="http://msdn2.microsoft.com/en-us/library/ms253051(VS.80).aspx"&gt;witexport&lt;/a&gt; to get a copy of the template and&amp;nbsp;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms253163(VS.80).aspx"&gt;witimport&lt;/a&gt;&amp;nbsp;to save it back to the server). The first think I noticed is that all the items in the "Active" state were flagged as having an invalid state because I had replaced "Active" with "Pending." There wasn't any batch method for updating these work items, so I had to change them one at a time. Fortunately, this is a young project, so there weren't many items that I had to change.&lt;/p&gt; &lt;p&gt;The next thing I found out&amp;nbsp;is that I had broken some of the reports. It turns out that the burn-down chart on the Project Portal page is from the Remaining Work report, and this report assumes that Tasks only have the Active and Closed states. That means all the Tasks in all the new states disappeared from this graph. Woops!&lt;/p&gt; &lt;h3&gt;Updating the Warehouse&lt;/h3&gt; &lt;p&gt;Since I needed do some more work and testing, I switched to a test TFS server so I wouldn't be working with the production server. However, this server didn't have Tasks in the other states, so I changed the state of a number of tasks. But since the warehouse isn't updated immediately, I needed to run the warehouse task. You can do this by running a web Service on the TFS reporting box:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;http://localhost:8080/Warehouse/v1.0/warehousecontroller.asmx?op=Run&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;You'll need to run this&amp;nbsp;web service method&amp;nbsp;from the TFS machine if you're using a browser to run it.&lt;/p&gt; &lt;h3&gt;Setting up Visual Studio to Customize Reports&lt;/h3&gt; &lt;p&gt;The reports in TFS are built on top of SQL Server Reporting Services, and Visual Studio has a way to edit the reports. However, getting it all set up wasn't exactly obvious. Here is how to set things up so you can edit and test reports.&lt;/p&gt; &lt;h4&gt;Download a Report&lt;/h4&gt; &lt;p&gt;The first step to customizing a report is to get a copy of the report from the server. There is an article on MSDN with the steps to get a local copy of the report: &lt;a href="http://msdn2.microsoft.com/en-us/library/ms181640(VS.80).aspx"&gt;How to: Locate and Edit a Report&lt;/a&gt;. However, this article is missing one important piece of information.&lt;/p&gt; &lt;h4&gt;Setting up the Data Sources&lt;/h4&gt; &lt;p&gt;The reports on the server that I downloaded uses two shared data sources with specific names. I needed to create these data sources in the Visual Studio project created in the previous step so they would have the same names, as defined in &lt;a href="http://msdn2.microsoft.com/en-us/library/ms404689(VS.80).aspx"&gt;Data Sources for Team Foundation Server Reporting&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;In order to set up data sources, you'll need to have access to the SQL Server machine with the TFSWarehouse database. I didn't have access to the production server, but I did have access to a test box with TFS on it, so I set the connection strings to point to the test box. Just right click on the &lt;strong&gt;Shared Data Sources&lt;/strong&gt; folder and select &lt;strong&gt;Add New Data Source&lt;/strong&gt; from the context menu to create a new datasource. Read &lt;a href="http://msdn2.microsoft.com/en-us/library/ms404689(VS.80).aspx"&gt;Data Soruces for Team Foundation Server Reporting&lt;/a&gt;&amp;nbsp;to setup the two data sources correctly (both point to the TFSWarehouse database, but they use different providers).&lt;/p&gt; &lt;p&gt;Here is what the project looked like after I setup the data sources:&lt;/p&gt; &lt;p&gt;&lt;a href="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/ReportsSolution4.gif" atomicselection="true"&gt;&lt;img height="180" src="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/ReportsSolution_thumb2.gif" width="262"&gt;&lt;/a&gt; &lt;/p&gt; &lt;h4&gt;Modifying and Testing the Report&lt;/h4&gt; &lt;p&gt;At this point I could double-click on the Remaing_Work.rdl report file and open it in the visual report designer. The report was initially setup to show only three values that correspond to the three states Active, Resolved, and Closed. Since I added new states to the Task template, I decided to add a new value for each state.&lt;/p&gt; &lt;p&gt;You add new state values to this report by clicking on the &lt;strong&gt;Layout&lt;/strong&gt; tab and then right-clicking on the graph and selecting &lt;strong&gt;Properties&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;In the &lt;strong&gt;Chart Properties&lt;/strong&gt; dialog box click on the &lt;strong&gt;Data&lt;/strong&gt; tab and then click on the &lt;strong&gt;Add&lt;/strong&gt; button to the right of the &lt;strong&gt;Values&lt;/strong&gt; list box. This will allow you to add a new value. For the value I used a variation of the expression that was already used for existing values:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;=Sum(IIF(Fields!State.Value="In Process",Fields!Cumulative_Count.Value,0))&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;All I had to do was change the name of the state in the State.Value= test. The resulting dialog looked like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/ChartProperties2.gif" atomicselection="true"&gt;&lt;img height="414" src="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/ChartProperties_thumb.gif" width="420"&gt;&lt;/a&gt; &lt;/p&gt; &lt;h4&gt;Test the Report&lt;/h4&gt; &lt;p&gt;Finally, if you have the connections setup properly, and have sufficient rights, you should be able to test your modified report on your computer using the &lt;strong&gt;Preview&lt;/strong&gt; tab of the Report Designer. The report should behave exactly as it would if you double-clicked on the report in the Team Explorer Reports folder.&lt;/p&gt; &lt;h4&gt;Upload Modified Report&lt;/h4&gt; &lt;p&gt;Once you have your report working the way you want, you'll need to upload it back to the server. The process for this is almost identical to downloading the report, except that you'll click on the &lt;strong&gt;Update&lt;/strong&gt; link instead of the &lt;strong&gt;Edit&lt;/strong&gt; link at the bottom of the page:&lt;/p&gt; &lt;p&gt;&lt;a href="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/ReportUpload3.gif" atomicselection="true"&gt;&lt;img height="486" src="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/ReportUpload_thumb3.gif" width="590"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here is what the chart looked like when I was all done:&lt;/p&gt; &lt;p&gt;&lt;a href="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/RemaingWorkModified1.gif" atomicselection="true"&gt;&lt;img height="377" src="http://socha.com/blogs/john/uploaded_images/TFSWorkItemStatesandReporting_D5BD/RemaingWorkModified_thumb1.gif" width="614"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This graph actually shows the before and after. Most of the graph shows Tasks that were based on the three original states, using data saved in the data warehouse. The last two days of the graph show the "Active" state split into&amp;nbsp;two of the new states: "Pending" and "In Process." As we move forward, we'll see even more states appear on this chart.&amp;nbsp;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-116594965236854872?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/12/customizing-tfs-work-item-states-and.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-116257687994858852</guid><pubDate>Fri, 03 Nov 2006 18:01:00 +0000</pubDate><atom:updated>2006-11-03T10:01:20.003-08:00</atom:updated><title>Simplifying VSTS Test Projects</title><description>&lt;p&gt;Every time I create&amp;nbsp;a new test project, it always adds some files I delete without even thinking. Today a colleague, Alan Ridlehoover, told me how to turn off some options that add these files to new test project.&lt;/p&gt; &lt;p&gt;If you select &lt;strong&gt;Options...&lt;/strong&gt; from the &lt;strong&gt;Tools&lt;/strong&gt; menu, and then click on the &lt;strong&gt;Test Project&lt;/strong&gt; node under the &lt;strong&gt;Test Tools&lt;/strong&gt; node, as shown below, you'll get the settings that allow you to remove these files. I decided to uncheck all these boxes.&lt;/p&gt; &lt;p&gt;&lt;a href="http://socha.com/blogs/john/uploaded_images/SimplifyingVSTSTestProjects_8B2F/UnitTestOptions2.gif" atomicselection="true"&gt;&lt;img height="382" src="http://socha.com/blogs/john/uploaded_images/SimplifyingVSTSTestProjects_8B2F/UnitTestOptions_thumb.gif" width="644"&gt;&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/18284077-116257687994858852?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/11/simplifying-vsts-test-projects.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-116007794349831414</guid><pubDate>Thu, 05 Oct 2006 19:52:00 +0000</pubDate><atom:updated>2006-10-05T14:19:02.003-07:00</atom:updated><title>"Brittle" Unit Tests</title><description>&lt;p&gt;I have a friend who is new to unit tests and therefore has never done Test-Drive Development. His management has decided that developers should now write unit tests. But there has been some debate about what should be tested. Since his "application" is really a class library, a lot of the functionality is hidden inside the library (the public API is just a small part).&lt;/p&gt; &lt;p&gt;Some of the people he talked to suggested not writing unit tests for the implementation (just test the public APIs) because they were nervous about making the library "brittle". As my friend said, "they define brittle as in it's really easy for someone to make a change and break stuff."&lt;/p&gt; &lt;p&gt;The comment about brittle unit tests is actually very interesting. I’ve encountered that myself. It’s frustrating when I have to go back and update unit tests after&amp;nbsp;doing a large refactoring. It certainly makes the unit tests “feel” brittle. But I think&amp;nbsp;this feeling is a result of changing&amp;nbsp;my approach to development rather than a real issue. I think it can be broken into two cases:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Unit tests fail, showing bugs in&amp;nbsp;my code. This is obviously the “good” case.  &lt;li&gt;Unit tests fail because assumptions have changed. This makes unit test feel brittle. But actually it’s a good thing. They fail because&amp;nbsp;my assumptions or “specifications” have changed. That means I really do need to rewrite the tests to reflect the new specifications that resulted from design changes.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;There is another way to look at item 2 above. Often&amp;nbsp;the broken unit tests are a result of bugs in the specifications, so what you're really faced with is having to interrupt what you were working on to fix bugs. This can certainly be unsettling, because it's a brick wall you have to scale before you can continue with your thread of thought. However, since you're fixing bugs as you go, your code will be much more reliable.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-116007794349831414?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/10/unit-tests.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-115998032290663060</guid><pubDate>Wed, 04 Oct 2006 16:45:00 +0000</pubDate><atom:updated>2006-10-04T09:45:23.463-07:00</atom:updated><title>Unit Tests for Learning and Experiments</title><description>&lt;p&gt;Very often when I'm learning a new set of APIs, I like to write some test code to try things out. In the past I would create a new Windows Forms project and put some buttons into the form. Then I'd put my test code into the Click event handler for the buttons and use the debugger to step through the code and look at the results.&lt;/p&gt; &lt;p&gt;Not anymore! Now that I've gotten used to using Test-Driven Development to write code, I now write the small learnings as unit tests, or as a unit tests that call some test code in my application. Since unit tests are run without starting up the entire application, they run very quickly.&lt;/p&gt; &lt;p&gt;I put this into practice just today working on some code that uses the XmlSerializer to serialize some of my objects. In this case my unit test is very simple:&lt;/p&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;pre class="csharpcode"&gt;[TestMethod]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ShouldSerialize()
{
    MapNode first = &lt;span class="kwrd"&gt;new&lt;/span&gt; MapNode(&lt;span class="str"&gt;"first"&lt;/span&gt;);
    MapNode second = &lt;span class="kwrd"&gt;new&lt;/span&gt; MapNode(&lt;span class="str"&gt;"second"&lt;/span&gt;);
    MapNode child = &lt;span class="kwrd"&gt;new&lt;/span&gt; MapNode(&lt;span class="str"&gt;"child"&lt;/span&gt;);
    first.Nodes.Add(child);
    MapNode[] nodes = &lt;span class="kwrd"&gt;new&lt;/span&gt; MapNode[] { first, second };
    FolderViewpointItem item = &lt;span class="kwrd"&gt;new&lt;/span&gt; FolderViewpointItem(10, nodes);

    XmlSerializer xml = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlSerializer(item.GetType());
    StringWriter writer = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringWriter();
    xml.Serialize(writer, item);
    Assert.Fail(writer.ToString());
}&lt;/pre&gt;Since I simply wanted to see the XML generated, I used the Assert.Fail method to display the XML as the message shown in Visual Studio's output window. Very fast, very simple. And I can use any of the classes in my application to try things out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-115998032290663060?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/10/unit-tests-for-learning-and.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-115816530561320359</guid><pubDate>Wed, 13 Sep 2006 16:35:00 +0000</pubDate><atom:updated>2006-09-13T09:35:05.646-07:00</atom:updated><title>How I Learned to Stop Worrying and Love TDD</title><description>&lt;p&gt;I've been a developer for many years, and I've prided myself in writing very reliable code. For example, The Norton Commander 3.0, the last version I wrote,&amp;nbsp;survived for&amp;nbsp;two years without a single maintenance release. One of the key factors that kept me writing reliable code was &lt;strong&gt;fear&lt;/strong&gt;. The fear that I would break the code and create a problem for users. I was always afraid that any major changes I made would break things. So whenever I made a major change, and I didn't let fear keep me from refactoring, I took my time and did lots of testing along the way. Fear was always at the back of my mind while I made these changes, so I really stressed about making sure I didn't make any mistakes.&lt;/p&gt; &lt;p&gt;That was before I discovered Test-Driven Development (TDD). I was introduced to TDD while contracting at Microsoft's &lt;a href="http://msdn.microsoft.com/practices/"&gt;patterns &amp;amp; practices&lt;/a&gt; group, working on the &lt;a href="http://msdn.microsoft.com/mobileclientfactory"&gt;Mobile Client Software Factory&lt;/a&gt;. The more I've used TDD, the more I like it.&lt;/p&gt; &lt;p&gt;I've now spent about a month working on a new project at p&amp;amp;p (more on this soon) and I had an epiphany today. I just realized that even though that fear is still there, it's much less grounded. Yesterday and today I did two major refactorings that before would have required very careful work and testing. However this time it was nearly painless. The unit tests I've written now do that work for me. So when I did the refactoring yesterday,&amp;nbsp;roughly 10% of the unit tests failed. It only took me about 15 minutes to fix the code so all the tests passed. Total time to make the refactoring was a lot less than it would have been using my old, fear-based approach to writing reliable code.&lt;/p&gt; &lt;p&gt;And this morning, to top it off, I just made another major refactoring change. Much to my amazement, I didn't break any of the unit tests. So after about 15 minutes of refactoring, I was done! Long live TDD!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-115816530561320359?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/09/how-i-learned-to-stop-worrying-and.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-115688017912517636</guid><pubDate>Tue, 29 Aug 2006 19:36:00 +0000</pubDate><atom:updated>2006-08-29T12:38:10.833-07:00</atom:updated><title>Viewing Compact Framework Source</title><description>&lt;p&gt;Many of us who develop for the Pocket PC have discovered that we can't use tools like &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Reflector&lt;/a&gt; to view to source code for the assemblies Microsoft provides, such as System.Windows.Forms. To see what I mean, try this. Open &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Reflector&lt;/a&gt; and from the &lt;strong&gt;File&lt;/strong&gt; menu, select &lt;strong&gt;Open List...&lt;/strong&gt; This will display the Assembly List Management dialog box, which allows you to create lists of assemblies so you can quickly load the assemblies you want into &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Reflector&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Next click on the &lt;strong&gt;Add&lt;/strong&gt; button to create a new assembly list. I called my list "Compact Framework 2.0". Click on the &lt;strong&gt;Select&lt;/strong&gt; button and you'll get a list of assemblies you can use to initially populate your new list. I selected &lt;strong&gt;.NET Compact Framework 2.0&lt;/strong&gt; from the &lt;strong&gt;Start 'Compact Framework 2.0' Assembly List&lt;/strong&gt; dialog box and then clicked on the &lt;strong&gt;OK&lt;/strong&gt; button to add these assemblies to the list.&lt;/p&gt; &lt;p&gt;Now if you open the a class, like ButtonBase in System.Windows.Forms, and display the source, you'll see something like this:&lt;/p&gt; &lt;p&gt;&lt;img height="343" src="http://socha.com/blogs/john/uploaded_images/ViewingCompactFrameworkSource_AA16/image020.png" width="559"&gt; &lt;/p&gt; &lt;p&gt;This certainly isn't very useful. Well, my colleague &lt;a href="http://clariusconsulting.net/blogs/kzu/"&gt;Daniel Cazzulino&lt;/a&gt; posted a question about this and got an &lt;a href="http://forums.microsoft.com/MSDN/showpost.aspx?postid=641409&amp;amp;siteid=1"&gt;answer&lt;/a&gt;. Now that I think about it, it makes perfect sense that you can't get source from the shipping assemblies. In order to keep the installed size as small as possible, the Compact Framework team removed the reflection information.&lt;/p&gt; &lt;p&gt;However, if you have Visual Studio, it ships with a separate set of assemblies that include all the reflection information. I created a new list in &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Reflector&lt;/a&gt;, but this time I clicked on the &lt;strong&gt;Cancel&lt;/strong&gt; button when it asked me what assemblies I wanted in my list. Then I selected &lt;strong&gt;Open&lt;/strong&gt; from the &lt;strong&gt;File&lt;/strong&gt; and and added the assemblies that were installed here on my computer:&lt;/p&gt; &lt;p&gt;C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\CompactFramework\2.0\v2.0\Debugger\BCL&lt;/p&gt; &lt;p&gt;Now I get the source code, as shown here, for the same exact class:&lt;/p&gt; &lt;p&gt;&lt;img height="133" src="http://socha.com/blogs/john/uploaded_images/ViewingCompactFrameworkSource_AA16/image026.png" width="389"&gt;&lt;/p&gt; &lt;p&gt;Very nice! Thanks Daniel!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-115688017912517636?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/08/viewing-compact-framework-source.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-115574976966207256</guid><pubDate>Wed, 16 Aug 2006 17:36:00 +0000</pubDate><atom:updated>2006-08-16T10:36:09.670-07:00</atom:updated><title>WYSIWYG Blog Editor</title><description>&lt;p&gt;I've a visual guy, so I really like to see what my blog will look like while I'm writing it. I've used some blog editors in the past, but had problems with them. Today I just discovered a really, really nice blog editor, called &lt;a href="http://windowslivewriter.spaces.live.com/"&gt;Windows Live Writer&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;What's really cool about this editor is that it works with my &lt;a href="http://www.blogger.com"&gt;Blogger&lt;/a&gt;, which is what I use for my blogs. And even better, it pulls down the template that I have on my site and let's me see exactly what my blog entry will look like while I write it. The colors are the same. The borders are the same. Etc. Very cool!&lt;/p&gt; &lt;p&gt;They also have an SDK, so it looks like there is a certain amount of customizing you can perform with plug-ins. I haven't looked at it yet, so I'm not sure what you can do.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-115574976966207256?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/08/wysiwyg-blog-editor.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-115574911541213133</guid><pubDate>Wed, 16 Aug 2006 17:25:00 +0000</pubDate><atom:updated>2006-08-16T10:27:59.556-07:00</atom:updated><title>New Resource for CAB Developers</title><description>&lt;p&gt;I recently started working on a project based on the &lt;a href="http://msdn.microsoft.com/practices/apptype/smartclient/default.aspx?pull=/library/en-us/dnpag2/html/cab.asp"&gt;Composite UI Application Block&lt;/a&gt; (CAB) from the &lt;a href="http://msdn.microsoft.com/practices/"&gt;patterns &amp;amp; practices&lt;/a&gt; group at Microsoft. I was initially lost and found it was difficult to find topics in the help. Like many developers, I don't like to read the manual before I get started, but it seems like the documentation is written more like a book than a help file. As a result, "topics" in the help file actually contain a number of topics and you have to scroll through looking for something that might be relevant. I also discovered that there weren't that many hyperlinks.&lt;/p&gt; &lt;p&gt;I also discovered lots of really useful information spread all over the net, mostly in blogs. But there didn't seem to a be a single, central source to find information.&lt;/p&gt; &lt;p&gt;Then it dawned on me. A Wiki would be a great place to have lots of useful information about CAB. So over a weekend I setup a Wiki to cover CAB and related technologies.&lt;/p&gt; &lt;p&gt;Please check out the site, and more importantly, please add to the site. This is a community site. Anyone can sign in and edit or add content.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a href="http://www.cabpedia.com"&gt;www.cabpedia.com&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-115574911541213133?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/08/new-resource-for-cab-developers.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-115473856481522839</guid><pubDate>Sat, 05 Aug 2006 00:38:00 +0000</pubDate><atom:updated>2006-08-05T18:12:22.450-07:00</atom:updated><title>Creating a Splash Screen in a CAB Application</title><description>&lt;p&gt;&lt;a href="http://msdn.microsoft.com/mobileclientfactory"&gt;We&lt;/a&gt; thought about adding support in &lt;a href="http://msdn.microsoft.com/mobileclientfactory"&gt;mobile CAB&lt;/a&gt; (Composite UI Application Block) for showing a splash screen at the very start of the application startup, but didn't get around to adding that support. I've just started working on a desktop application based on CAB, so now I'm actually a user of CAB instead of a "developer" of mobile CAB. As it turns out, it's very easy to add a splash screen.&lt;/p&gt;&lt;p&gt;The information below is based on a CAB application created using the &lt;a href="http://codegallery.gotdotnet.com/scbat"&gt;Smart Client Software Factory&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Once you get beyond the most basic of CAB applications, it can take a while to load the application. Most applications have splash screens that appear as early in the process as possible and go away once the main UI appears. Here is a simple way you can do this in your own applications.&lt;/p&gt;&lt;h3&gt;Create A new Application Class&lt;/h3&gt;&lt;p&gt;First create a new Application generic you'll use to start your application. For example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SmartClientSplashApplication&amp;lt;TWorkItem, TShell, TSplash&amp;gt;
       : SmartClientApplication&amp;lt;TWorkItem, TShell&amp;gt;
   &lt;span class="kwrd"&gt;where&lt;/span&gt; TWorkItem : WorkItem, &lt;span class="kwrd"&gt;new&lt;/span&gt;()
   &lt;span class="kwrd"&gt;where&lt;/span&gt; TShell : Form
   &lt;span class="kwrd"&gt;where&lt;/span&gt; TSplash : Form, &lt;span class="kwrd"&gt;new&lt;/span&gt;()
{
   &lt;span class="kwrd"&gt;private&lt;/span&gt; TSplash _splash;

   &lt;span class="kwrd"&gt;public&lt;/span&gt; SmartClientSplashApplication()
   {
       _splash = &lt;span class="kwrd"&gt;new&lt;/span&gt; TSplash();
       _splash.Show();
   }

   &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AfterShellCreated()
   {
       &lt;span class="kwrd"&gt;base&lt;/span&gt;.AfterShellCreated();
       Shell.Activated += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(Shell_Activated);
   }

   &lt;span class="kwrd"&gt;void&lt;/span&gt; Shell_Activated(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
   {
       Shell.Activated -= &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(Shell_Activated);
       _splash.Hide();
       _splash.Dispose();
       _splash = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
   }
}&lt;/pre&gt;&lt;h2&gt;Create a Splash Screen&lt;/h2&gt;&lt;p&gt;The splash screen is a form that has something on it, like a bitmap and perhaps some text, like the version number and a copyright. You can also set the border to None so you don't see the usual window. After all, it's shown while the application is loading, so you can't close it yourself.&lt;/p&gt;&lt;h2&gt;Change Program.cs&lt;/h2&gt;&lt;p&gt;Finally, modify the startup code in Program.cs, or ShellApplication.cs if it was generated by the Smart Client Software Factory, to use this new generic class:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; ShellApplication : SmartClientSplashApplication&amp;lt;WorkItem, ShellForm, SplashForm&amp;gt;
...      
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-115473856481522839?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/08/creating-splash-screen-in-cab.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-115471067000834037</guid><pubDate>Fri, 04 Aug 2006 16:53:00 +0000</pubDate><atom:updated>2006-08-04T09:57:50.450-07:00</atom:updated><title>Microsoft patterns &amp; practices Mobile Client Software Factory</title><description> &lt;p&gt;I just spent the last 7 months working as a contractor at Microsoft, in their &lt;a href="http://patterns.gotdotnet.com/"&gt;patterns &amp;amp; practices&lt;/a&gt; group. They hired me to help create their &lt;a href="http://msdn.microsoft.com/mobileclientfactory"&gt;Moblile Client Software Factory&lt;/a&gt;; this project was very rewarding and a lot of fun. They needed an expert on mobile development, which is where I came into the picture. I always wanted to see what it was like to work at Microsoft, and the fact that I live about 1-1/2 miles (as the crow flies) from Microsoft made the transition easy.&lt;/p&gt; &lt;p&gt;This group uses a number of practices that were new to me. All their projects are developed using Agile practices, which includes some of the following areas that were new to me:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Test-Driven Development&lt;/li&gt; &lt;li&gt;Pair Programming&lt;/li&gt; &lt;li&gt;The entire team is in a team room&lt;/li&gt; &lt;li&gt;Rapid iterations&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;There are more points, but that should give you a starting point. As a programmer, I've always worked in a private office so I could focus and not be distracted. The idea of working in a team environment, without a quiet place to work, was different than what I was used to, but hey, it was a contract. If I'd come into a full-time job where I wouldn't have my own office, I think I would have been very reluctant to accept the offer. After all, I really need my quiet to focus and get my job done. Or so I thought...&lt;/p&gt; &lt;p&gt;Fast forward 7 months. I proposed a new project in the &lt;a href="http://patterns.gotdotnet.com/"&gt;patterns &amp;amp; practices&lt;/a&gt; group and got it funded, so I'm now working on a new project under contract. I was offered the use of someone else's office, but I chose instead to find space in another team room. What's that you're saying? Why would I chose a noisy team room over a quiet office?&lt;/p&gt; &lt;p&gt;The answer is a little complicated, but it's also something everyone else here has discovered. None of the people here wanted to give up private offices. However, now that they've experienced the agile environment, they don't want to go back to private offices. There are several reasons for this.&lt;/p&gt; &lt;p&gt;First, the dynamic of a team environment really does provide better shared knoweledge of the project. You feal more involved because you are more involved. And you have a better sense of how all the pieces fit together and what other people are working on.&lt;/p&gt; &lt;p&gt;However, more importantly is the dynamic of pair programming. Here you have two people on one computer. We've done it where we have two keyboards and mice on a single computer. One person writes a unit test describing what the code should do, and then the other person writes the minimal amount of code to make that unit test pass. Next you switch roles. This process produces simpler, more reliable code than you get from a single programmer, and it also makes keeping your energy level high during the project easier.&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-115471067000834037?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2006/08/microsoft-patterns-practices-mobile.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-113590535658528028</guid><pubDate>Fri, 30 Dec 2005 01:15:00 +0000</pubDate><atom:updated>2005-12-29T17:15:56.610-08:00</atom:updated><title>NUnit and Compact Framework Applications</title><description>&lt;p&gt;I recently learned about Test Driven Development and got really excited. Until, that is, I discovered that my version of Visual Studio doesn't have the great new tools for team development. For that you need one of the Team editions, but at more than $5,000, I wasn't quire ready to take the plunge.&lt;/p&gt;&lt;p&gt;So I decided to try &lt;a href="http://www.nunit.org/"&gt;NUnit&lt;/a&gt;, which is an open source application for testing .NET applications.And it works, within some well-defined cases.&lt;/p&gt;&lt;p&gt;There are limits to what you can and cannot test using NUnit to test your Windows Mobile applications. Since NUnit is running on the desktop, your unit tests also run on the desktop rather than a Windows Mobile platform (device or emulator). If your testing code that isn't dependent on the Windows Mobile platform, you should be able to write and run unit tests on the desktop because your CF applications classes will load and run on the desktop as long as they don't require PocketPC/Smartphone-specific code (such as PInvoke calls to coredll).&lt;/p&gt;&lt;p&gt;Of course, it would be far better to test your code on the target platform, or at least for some test cases. Right now there is only one test harness I'm aware of that runs on Windows Mobile itself: &lt;a href="http://cfnunitbridge.tigris.org/"&gt;CFNUnitBridge&lt;/a&gt;. I haven't tried this yet, but I'm just getting started with test-driven development.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-113590535658528028?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2005/12/nunit-and-compact-framework.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-113590439520430745</guid><pubDate>Sat, 03 Dec 2005 02:46:00 +0000</pubDate><atom:updated>2005-12-29T16:59:55.290-08:00</atom:updated><title>A resource nightmare on .NET street</title><description>&lt;p&gt;Well, I had a fun afternoon. I have a program for the Pocket PC that I just put into alpha. I've written this program using the .NET Compact Framework 1.1. I of course upgraded my development environment to Visual Studio 2005 when it was released about a month ago, however I continued to use version 1.1 of the .NET CF. No problem.&lt;/p&gt;&lt;p&gt;That is, until today when I decided to change one string in my resource file. Once I did that, I kept getting runtime errors when I attempted to read a value from the embedded string resource. First I got an ArgumentError exception, then I got a TypeLoadException. How could that be? My resource code has been working for a long time and I didn't change a single line of code--I just edited the value of a resource string.&lt;/p&gt;&lt;p&gt;After a number of hours trying different things I finally figured it out. I hadn't edited the resource file in quite some time and, as it turned out, I had upgraded the program I was using to edit my resource files, which were in the ".resource" format. I started using a program called &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Resourcer&lt;/a&gt; back when I was using Visual Studio 2002. Recently I decided to get the latest and greatest version, which was labeled ".NET Framework 2.0.50727." What I didn't know, and which now makes sense, is that the author, Lutz Roeder, delivers three different versions of the same program that bind to different versions of the .NET framework. And each of these versions writes a .resource file tied to the same version of the .NET framework.&lt;/p&gt;&lt;p&gt;So when I modified a string and saved the file, &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Resourcer&lt;/a&gt; overwrote the old .NET 1.1 file with a .NET 2.0 file. When I looked more closely at the strings in this file, I noticed that the type for each string is "System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKey Token=b77a5c561934e089." Notice the version number? When I called the resource manager's GetObject method, it attempted to create a 2.0 instance of the type, but this application is running on a device with 1.1 on it, so the create failed.&lt;/p&gt;&lt;p&gt;But the story doesn't end there. I wasn't able to open this file with a "previous" version of &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Resourcer&lt;/a&gt; because the versions for older .NET frameworks weren't able to load the newer types. Fortunately, I was able to use &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Resourcer&lt;/a&gt; to save the file as a .resX file, which I could then include in my project. In the process, I also discovered that Visual Studio 2005 contains a fabulous built-in resource editor that makes &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Resourcer&lt;/a&gt; obsolete.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-113590439520430745?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2005/12/resource-nightmare-on-net-street.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-18284077.post-113045363532253016</guid><pubDate>Thu, 27 Oct 2005 22:53:00 +0000</pubDate><atom:updated>2005-10-27T15:53:55.346-07:00</atom:updated><title>ListChanged in PocketOutlook on Windows Mobile 5.0</title><description>I've been working on a calendar application for the Pocket PC. Now that Windows Mobile 5.0 devices are shipping, I figured I should ensure my application works on Windows Mobile 5.0. There is one feature I added that doesn't work anymore--my application doesn't receive notification when the calendar changes. For previous versions of the Pocket PC, I was able to trap changes to the appropriate CEDB property database via some C++ code. However, Windows Mobile 5.0 uses a new, and incompatible, database to store PIM information, so my change hook from before doesn't work.&lt;br/&gt;&lt;br/&gt;I was thus very excited to discover Microsoft had shipped a managed assembly for use on Windows Mobile 5.0 that supports receiving change notification. Their assembly, Microsoft.&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/H_home.asp"&gt;WindowsMobile&lt;/a&gt;.&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/N_Microsoft_WindowsMobile_PocketOutlook.asp" title="Microsoft.WindowsMobile.PocketOutlook"&gt;PocketOutlook&lt;/a&gt; has a number of classes that correspond with POOM (Pocket Outlook Object Model) objects. In particular, the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/T_Microsoft_WindowsMobile_PocketOutlook_PimItemCollection.asp"/&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/E_Microsoft_WindowsMobile_PocketOutlook_PimItemCollection_ListChanged.asp" title="PimItemCollection"&gt;PimItemCollection&lt;/a&gt; class contains an event called &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/E_Microsoft_WindowsMobile_PocketOutlook_PimItemCollection_ListChanged.asp"&gt;ListChanged&lt;/a&gt;. Perfect! Or so I thought.&lt;br/&gt;&lt;br/&gt;Testing this code when changing or adding an appointment using the Calendar application didn't work. What gives? It turns out the ListChanged event doesn't receive change notifications from the operating system. Instead, it only tells you of changes made "to the collection." In other words, if &lt;strong&gt;your&lt;/strong&gt; application uses the managed classes to modify, add, or remove an appointment, &lt;strong&gt;your&lt;/strong&gt; application will be notified. If any other application changes the calendar (or any of the other supported databases), you do not receive notification. In other words, you can use the managed event to keep your application current with the data in the database. This is documented in the Wiki article &lt;a href="http://channel9.msdn.com/wiki/default.aspx/MobileDeveloper.ManagedAPIs"&gt;Windows Mobile 5.0 Managed &lt;span style="DISPLAY: none" id="id6267"&gt;Documentation for the Windows Mobile APIs&lt;/span&gt;&lt;/a&gt; on &lt;a href="http://channel9.msdn.com/"&gt;Channel 9&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;So, I'm back to adding C++ code that will support Windows Mobile 5.0.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Related Articles&lt;/strong&gt;&lt;br/&gt;&lt;blockquote style="MARGIN-RIGHT: 0px" dir="ltr"&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnppcgen/html/whatsnew_wm5.asp" title="What's New for Developers in Windows Mobile 5.0"&gt;What's New for Developers in Windows Mobile 5.0&lt;br/&gt;&lt;/a&gt;&lt;br/&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18284077-113045363532253016?l=www.socha.com%2Fblogs%2Fjohn' alt='' /&gt;&lt;/div&gt;</description><link>http://www.socha.com/blogs/john/2005/10/listchanged-in-pocketoutlook-on.html</link><author>noreply@blogger.com (John Socha-Leialoha)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item></channel></rss>