<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Data Otaku</title><subtitle type="html">A seemingly random collection of data- and database-related posts</subtitle><id>http://blogs.msdn.com/b/data_otaku/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/b/data_otaku/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2011-06-26T08:21:00Z</updated><entry><title>Presenting Actuals and Forecast Concurrently in a Write-Enabled Cube</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2013/01/26/presenting-actuals-and-forecast-concurrently.aspx" /><link rel="enclosure" type="application/zip" length="478075" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-38-85-52/Utilization.zip" /><id>http://blogs.msdn.com/b/data_otaku/archive/2013/01/26/presenting-actuals-and-forecast-concurrently.aspx</id><published>2013-01-26T18:00:00Z</published><updated>2013-01-26T18:00:00Z</updated><content type="html">&lt;p&gt;I have written a series of entries on writeback applications and wanted to add this last entry highlighting a common cube design challenge associated with these.&amp;nbsp; Quite often with write enabled cubes, we enter forecasted data for future periods.&amp;nbsp; When those periods come to pass we bring in actual (historical) data into the data model while holding onto our forecasts for these periods.&amp;nbsp; And while its easy enough to present forecasted values side-by-side with actual values, we often wish to look over longer spans of time at a single set of values some of which represent actuals and others of which represent forecasts.&lt;/p&gt;
&lt;p&gt;To illustrate this, consider a utilization model for employees in a consultancy.&amp;nbsp; In this model, we forecast the number of hours we expect each employee to work over the weeks of a year with the objective of understanding the utilization percentage those employees will obtain.&amp;nbsp; (In a consultancy, maintaining individual and organizational utilization rates (percentages)&amp;nbsp;are critical for ensuring profitability and avoiding employee burn-out and turn-over.)&lt;/p&gt;
&lt;p&gt;As we look at an employee's utilization potential utilization rate for a given year, we have some weeks for which we must forecast values and other weeks for which the employee has submitted his or her actual values.&amp;nbsp; The end of the year utilization rate represents a combination of forecasted and actual values.&lt;/p&gt;
&lt;p&gt;In our cube, we typically keep forecasted and actual values separated by either employing two separate measure groups,&lt;em&gt; i.e.&lt;/em&gt; one for actuals and another for forecast, or by recording both sets of values in a single measure group by assigning actuals to a scenario member in a Scenario dimension that is reserved just for actuals. In the sample database I've provided with this post, I've used to former approach to keep things a bit more simple.&lt;/p&gt;
&lt;p&gt;To present actuals and forecast data together, I've modified an otherwise standard Time dimension by adding an attribute, [Is Actual], which is used to identify dates that have passed (and for which I therefore have actuals) and dates that are yet to come (and for which I must rely on forecasted values).&amp;nbsp; I then created a calculated member, [Measures].[Hours], where I bring together actuals and forecasted values based on their association with the [Is Actual] attribute.&amp;nbsp; Here's the calculation:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;([Measures].[Actuals],[Date].[Is Actual].[True]) + ([Measures].[Forecast],[Date].[Is Actual].[False])&lt;/p&gt;
&lt;p&gt;The result of this expression is that when I am reviewing a time period comprised solely of actuals, the first part of the expression returns a value while the second returns nothing.&amp;nbsp; When I review a period that is comprised solely of forecast, the opposite is true.&amp;nbsp; And when I review a period that should be represented partly by actuals and partly by forecast, each side of the equation returns the proper part.&amp;nbsp; Utilization is then calculated of this "combined" measure.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10388552" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>UPDATED: Getting the Timeline Filter (Slicer) in Excel 2013 to Work with an Analysis Services OLAP Cube</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/11/30/getting-the-timeline-filter-slicer-in-excel-2013-to-work-with-an-analysis-services-olap-cube.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/11/30/getting-the-timeline-filter-slicer-in-excel-2013-to-work-with-an-analysis-services-olap-cube.aspx</id><published>2012-11-30T20:05:00Z</published><updated>2012-11-30T20:05:00Z</updated><content type="html">&lt;p&gt;In Excel 2013, there is a new Timeline filter (slicer) that allows you to easily select a range of dates over which you want to filter your data. The feature is very slick.&amp;nbsp; Here's an picture:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/7220.timeline.png"&gt;&lt;img src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/7220.timeline.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I wanted to use this slicer in an Analysis Services demo but run into a bit of an issue getting this to work with&amp;nbsp;my OLAP cube.&amp;nbsp; After spending a little time with the Excel team, it turns out that this slicer picks up on the MemberValue property.&amp;nbsp; If you map an attribute's MemberValue property to a field that uses a date data type, the Timeline filter is available to you.&lt;/p&gt;
&lt;p&gt;In my scenario, that means that I'm setting up a Date dimension with a leaf-level Date attribute.&amp;nbsp; That attribute's MemberKey property is assigned to an integer surrogate key column and it's MemberName property is assigned to a friendly formatted string (WChar)&amp;nbsp;column.&amp;nbsp; I have set up all my Type properties (on the dimension and this and other attributes) as you would expect (because I want to use some of the Time Intelligence features in Analysis Services).&amp;nbsp; And now I&amp;nbsp;map the MemberValue property on the Date attribute to an actual&amp;nbsp;field using a Date data type to enable the Timeline filter.&lt;/p&gt;
&lt;p&gt;It turns out that in Excel 2010 &amp;amp; 2007&amp;nbsp;this same step (of assigning the MemberValue property to a date data type field) triggers a Date Filter drop-down on row and column filters.&amp;nbsp;&amp;nbsp;Who knew?! :-)&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; After posting this, Greg Galloway sent me &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=9982"&gt;this link&lt;/a&gt; to an Excel 2007 document identifying OLAP design practices that will light up functionality in the Pivot Table.&amp;nbsp; This includes the Date filtering mentioned above.&amp;nbsp; The requirements mentioned there are that the dimension has a Type of Time and the leaf-level attribute has a MemberValue property mapped to a field with a date data type.&amp;nbsp; These are the exact constraints on the Timeline filter.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10373619" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Writeback Application Code Samples</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/writeback-application-code-samples.aspx" /><link rel="enclosure" type="application/zip" length="729101" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-33-20-31/Writeback.zip" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/writeback-application-code-samples.aspx</id><published>2012-07-20T17:33:32Z</published><updated>2012-07-20T17:33:32Z</updated><content type="html">&lt;p&gt;In order to help folks get started with writeback applications, I'm posting here an Analysis Services database, it's associated data source, and three sample Excel applications demonstrating different forms of writeback.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;By downloading these, you assume all risk and agree to work with these in an isolated, test&amp;nbsp;environment only. I want to make sure I'm clear that these are not thoroughly tested, do not employ validation or error handling, and are otherwise in no way ready for a production deployment.&lt;/p&gt;
&lt;p&gt;That said, if you do download and use these, you'll need to change the data source connection string in the Analysis Services database to point to wherever you deployed the WritebackDemo database.&amp;nbsp; You'll need to deal with permissions issues between your Analysis Services instance and SQL Server Database Engine instance.&amp;nbsp; You'll also need to modify the connections in the workbooks; these are accessible through the Data tab's Connections item.&lt;/p&gt;
&lt;p&gt;Also, I should note that both databases use SQL Server 2012 RTM.&amp;nbsp; You should be able to download a copy of Evaluation Edition to get these to work if you do not otherwise have Developer Edition available to you.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I hope these are helpful in demonstrating the concepts explained in the posts and giving you&amp;nbsp;a starting point for your writeback applications.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10332031" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Managing Writeback Cubes</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/managing-writeback-cubes.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/managing-writeback-cubes.aspx</id><published>2012-07-20T17:23:04Z</published><updated>2012-07-20T17:23:04Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt; This is part of a series of entries on the topic of &lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" face="Calibri" color="#0000ff" size="3"&gt;Building Writeback Applications with Analysis Services&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In presenting on the topic of writeback applications with Analysis Services, there are a few administrative questions that seem to come up which I will attempt to address here.&amp;nbsp; These tend to be focused on:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&amp;middot;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Backup &amp;amp; Recovery&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&amp;middot;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Writeback Partition Maintenance&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&amp;middot;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Update Conflicts&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Backup &amp;amp; Recovery&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The writeback application is dependent on a number of assets. These include the user-interface and any supporting components, the Analysis Services database, the source database(s) and the writeback partition table.&amp;nbsp; Assuming you have the user-interface and supporting components covered, I&amp;rsquo;ll focus on the AS database, source database(s) and writeback partition table which I&amp;rsquo;ll refer to collectively as the data assets.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To recover the data assets, you need to implement standard backup procedures. If you limit your cube to a single source database and keep your writeback partition table in that database, then you can backup and recovery that database without a potential loss in data consistency.&amp;nbsp; That said, there is the potential for the source database (including the writeback partition table) to be inconsistent with data in the Analysis Services database.&amp;nbsp; If you must recover one or the other or both, execute a full process on the Analysis Services database following recovery in order to ensure they are in sync.&amp;nbsp; As Analysis Services databases associated with writeback applications tend to be relatively small, the full process should not be too burdensome.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Writeback Partition Maintenance&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;I cannot stress this enough.&amp;nbsp; LEAVE THE WRITEBACK PARTITION TABLE ALONE! If you are concerned about performance, use the MOLAP storage option for the writeback partition as this will improve query performance even when there are large numbers of entries in this table.&amp;nbsp; If there has been an invalid writeback operation, consider correcting it with another writeback operation.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;If you do modify the data in the table &amp;ndash; did I mention that I really think you shouldn&amp;rsquo;t do this? &amp;ndash; then be sure to process the associated measure group once you are done to ensure it is in sync with the new data in the table.&amp;nbsp; This goes for whether you are employing MOLAP or ROLAP for your writeback partition.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;If you are bringing in additional data to your data source, such as data flowing in through an ETL process, model your data in such a way that that data is separated from the writeback entries.&amp;nbsp; Some examples of how to do this include having a measure group for actuals and another for forecast where actuals enter the database through ETL and forecast enter the database through writeback.&amp;nbsp; Another approach is to assign incoming data to a special scenario, e.g. an Observed, Actuals, or Historical scenario, and have writebacks take place against other scenarios.&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;There are many ways you can ensure that new data coming into your data source do not invalidate the writeback entries.&amp;nbsp; If you cannot then you may have to assume that with a data update (through the ETL) the writeback entries are no longer valid.&amp;nbsp; In this case, you may need to delete entries from the writeback partition table (or truncate the whole table) to reset the data.&amp;nbsp; If you do this, be sure to process the associated measure group in the cube to make sure it is in sync.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Finally, please be aware that making changes to a measure group with a writeback partition may require the structure of the writeback partition table to change.&amp;nbsp; Once a writeback application is in use, you must carefully consider how any changes to a measure group receiving writebacks will be implemented.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Update Conflicts&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;When a user writes back to a cube, the changes are held in memory as part of a connection-specific writeback cache.&amp;nbsp; That cache is isolated from other users so that the associated user can perform multiple cycles of What-If analysis before publishing or discarding those changes.&amp;nbsp; Only when those changes are published (committed) are they potentially exposed to other users.&amp;nbsp; So, how does Analysis Services deal with the potential situation within which two users are writing back to overlapping parts of the cube?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In short, it doesn&amp;rsquo;t.&amp;nbsp; If one user makes changes while another user makes changes, they are isolated from one another.&amp;nbsp; If one user publishes his or her changes, there is no signal to the other user that the data he or she is working with is no longer current.&amp;nbsp; If the other user commits his or her changes not knowing the first user has made changes, the other user&amp;rsquo;s changes overwrite the first user&amp;rsquo;s changes and become the current state of the data.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;At first this sounds terrible, but let&amp;rsquo;s think about this a little further.&amp;nbsp; Writeback applications are intended to be expert systems.&amp;nbsp; This assumes a limited number of users with writeback permissions.&amp;nbsp; Next, can use dimension data and cell data security to control to which parts of the cube individual users can write and in doing so can ensure we have few potential overlapping writes.&amp;nbsp; And finally, if we are building a custom application, we can always open a second connection and validate the state of the data prior to committal.&amp;nbsp; This later step is a little extreme to me for most applications, but if you were not mitigate the problem with limited numbers of writeback users and avoidance of overlapping write-enabled portions of the cube, it&amp;rsquo;s another option.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" face="Times New Roman" size="3"&gt; &lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10332025" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Writeback to a Regular Dimension</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/writeback-to-a-regular-dimension.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/writeback-to-a-regular-dimension.aspx</id><published>2012-07-20T14:46:00Z</published><updated>2012-07-20T14:46:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt; This is part of a series of entries on the topic of &lt;/span&gt;&lt;/span&gt;&lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" face="Calibri" size="3" color="#0000ff"&gt;Building Writeback Applications with Analysis Services&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;In the post on &lt;/span&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/19/writeback-to-a-parent-child-dimension.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" face="Calibri" size="3" color="#0000ff"&gt;writeback to a parent-child dimension&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;, writeback was implemented using the ALTER CUBE MDX statement.&amp;nbsp; If you attempt to use that statement to writeback to a regular dimension you will get an error stating that &amp;ldquo;Dimension writeback using this syntax is supported only on parent-child members.&amp;rdquo;&amp;nbsp; To get around this, you&amp;rsquo;ll need to writeback to a regular dimension using one of three XMLA commands.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Before diving into those commands, it should be pointed out that this isn&amp;rsquo;t as intimidating as it might sound.&amp;nbsp; The commands themselves follow some simple patterns, and once you learn these and get past the verbose inclusion of namespaces they are surprisingly straightforward.&amp;nbsp; In addition, the pattern established before with opening a connection in ADO or ADO.NET using the MSOLAP provider works the same with XMLA as it does with MDX.&amp;nbsp; Finally, it&amp;rsquo;s worth noting that these XMLA commands could be used in place of the ALTER CUBE MDX statement for updating a parent-child dimension as well.&amp;nbsp; I focused on the ALTER CUBE statement in the previous post simply because that&amp;rsquo;s the traditional pattern used for these kinds of applications.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The Basic Structure of the XMLA Commands&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To add, modify, or delete a dimension record in a regular dimension, you&amp;rsquo;ll use the Insert, Update, or Drop XMLA commands. The basic structure of these commands is as follows:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&amp;lt;&lt;b&gt;Command &lt;/b&gt;&amp;nbsp;&amp;nbsp;xsi:type=&lt;b&gt;"Command" &lt;br /&gt; &lt;/b&gt;&amp;nbsp; xmlns:xsd="http://www.w3.org/2001/XMLSchema" &lt;br /&gt; &amp;nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" &lt;br /&gt; &amp;nbsp; xmlns:ddl2="http://schemas.microsoft.com/analysisservices/2003/engine/2" &lt;br /&gt; &amp;nbsp; xmlns:ddl2_2="http://schemas.microsoft.com/analysisservices/2003/engine/2/2" &lt;br /&gt; &amp;nbsp; xmlns:ddl100_100="http://schemas.microsoft.com/analysisservices/2008/engine/100/100" &lt;br /&gt; &amp;nbsp; xmlns:ddl200="http://schemas.microsoft.com/analysisservices/2010/engine/200" &lt;br /&gt; &amp;nbsp; xmlns:ddl200_200="http://schemas.microsoft.com/analysisservices/2010/engine/200/200" &lt;br /&gt; &amp;nbsp; xmlns="http://schemas.microsoft.com/analysisservices/2003/engine"&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;&amp;lt;Object&amp;gt; &amp;hellip; &amp;lt;/Object&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Command Specific Elements/&amp;gt;&lt;br /&gt; &lt;/b&gt;&amp;lt;/&lt;b&gt;Command&lt;/b&gt;&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In place of the word Command, you will use Insert, Update or Drop.&amp;nbsp; Be sure to employ the appropriate command name for the opening and closing tags of the XMLA statement, but also use the command name with the xsi:type attribute.&amp;nbsp; In addition, be sure to follow the sentence case pattern &amp;ndash; first letter in upper case and the remaining in lower case - used in the sample above.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The Object element in these commands identifies the database and dimension being operated on and is consistent across all three commands:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&amp;lt;Object&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Database&amp;gt;Writeback&amp;lt;/Database&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Cube&amp;gt;&lt;b&gt;$Project&lt;/b&gt;&amp;lt;/Cube&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Dimension&amp;gt;&lt;b&gt;Project&lt;/b&gt;&amp;lt;/Dimension&amp;gt;&lt;br /&gt; &amp;lt;/Object&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Notice in this element that a cube is identified.&amp;nbsp; For the cube element, provide the name of the database-level dimension (not a cube dimension) you are updating preceded by a dollar-sign.&amp;nbsp; If you are curious as to why this is, the short answer is that you are modifying a dimension object that exists at the Analysis Services database level.&amp;nbsp; At that level, a dimension is thought of as its own cube.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In addition to these elements, the commands will make use of one or more additional elements, namely the Attributes and Where elements, depending on the specific command employed.&amp;nbsp; These will be addressed in the context of the specific commands in the following sections.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Adding a Dimension Member&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To add a dimension member, use the Insert command.&amp;nbsp; This command follows the basic pattern described above and employs the additional Attributes element.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The Attributes element identifies one or more attributes for the newly added dimension entry as demonstrated in this sample:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&amp;lt;Attributes&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;b&gt;Attribute&lt;/b&gt;&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;b&gt;AttributeName&lt;/b&gt;&amp;gt;Project&amp;lt;/&lt;b&gt;AttributeName&lt;/b&gt;&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;b&gt;Name&lt;/b&gt;&amp;gt;Project 06&amp;lt;/&lt;b&gt;Name&lt;/b&gt;&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;b&gt;Keys&lt;/b&gt;&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;b&gt;Key&lt;/b&gt;&amp;gt;Project 06&amp;lt;/&lt;b&gt;Key&lt;/b&gt;&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;b&gt;Keys&lt;/b&gt;&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;b&gt;Attribute&lt;/b&gt;&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Attribute&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;AttributeName&amp;gt;Owner&amp;lt;/AttributeName&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Name&amp;gt;Owner 02&amp;lt;/Name&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Keys&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Key&amp;gt;Owner 02&amp;lt;/Key&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Keys&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Attribute&amp;gt;&lt;br /&gt; &amp;lt;/Attributes&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;As you can see in this sample, an entry in the Project dimension has two attributes, Project and Owner, as identified by the AttributeName element under each Attribute element.&amp;nbsp; For each attribute, we identify a name and key value.&amp;nbsp; If an attribute has a multi-part key, each key value is specified in the order in which they are defined for the attribute, but as each attribute here has a single key, only one Key element is employed under each Keys element.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;The Attribute element has many more sub-elements so that you are not limited to the items identified here.&amp;nbsp; For more information on what can be prescribed to an attribute through the Attribute element, please refer to &lt;/span&gt;&lt;a href="http://technet.microsoft.com/en-us/library/ms186618.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" face="Calibri" size="3" color="#0000ff"&gt;this entry in Books Online&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Dropping a Dimension Member&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To drop a dimension member, use the Drop XMLA command.&amp;nbsp; As with the Insert command, Drop follows the basic pattern discussed at the top of this entry, but its one command-specific element is the Where element.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The Where element behaves very much like a WHERE clause in a SQL statement.&amp;nbsp; Think of it as specifying matching criteria which can identify one or more entries in a dimension. In the Where element, one or more attributes are identified by attribute name and key value.&amp;nbsp; If multiple attributes are supplied, these are considered using OR logic.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In this example, one attribute is specified so that this Where element can be thought of as behaving as a SQL WHERE clause with &lt;i&gt;Project = &amp;lsquo;Project 06&amp;rsquo;&lt;/i&gt; as its logic:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&amp;lt;Where&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Attribute&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;AttributeName&amp;gt;Project&amp;lt;/AttributeName&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Keys&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Key&amp;gt;Project 06&amp;lt;/Key&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Keys&amp;gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Attribute&amp;gt;&lt;br /&gt; &amp;lt;/Where&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&amp;nbsp;If you would like to ensure that only one row is identified through a Where element, specify criteria for nothing more than your leaf-level attribute.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Modifying a Dimension Member&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Dimension members are modified using the Update XMLA statement. This statement follows the basic structure identified at the top of this post and makes use of both the Attributes and Where elements.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;As with the Drop command, the Where element when used with the Update command identifies the dimension members you wish to affect.&amp;nbsp; The Attributes element, structured same as it is with the Insert command, identifies the new values for these members.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Executing the XMLA Commands&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;I&amp;rsquo;ve said a few times that the XMLA commands are executed using the same pattern you&amp;rsquo;ve used the MDX statements.&amp;nbsp; You simply open a connection using the MSOLAP provider, execute the statement, and then close the connection.&amp;nbsp; But given that XMLA is so different from MDX, I want to make sure I am being crystal clear about this.&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Here is a code sample, written in VBA, that demonstrates this pattern.&amp;nbsp; The MyStatement variable can be assigned either the ALTER CUBE MDX statement or one of the three XMLA commands addressed here and it will work the same:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000;"&gt;'Add reference to Microsoft ActiveX Data Objects 6.0 Library&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;'MyStatement is either ALTER CUBE or one of the XMLA DDL statements but defined somewhere else&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000;"&gt;'1. Establish Connection to Analysis Services Database&lt;/span&gt;&lt;br /&gt;Dim cn As New ADODB.Connection&lt;br /&gt;cn.Open "Provider=MSOLAP;Data Source=localhost;Initial Catalog=Writeback Demo;"&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000;"&gt;'2. Execute Command &amp;amp; Commit Transaction&lt;/span&gt;&lt;br /&gt;cn.Execute MyStatement&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000;"&gt;'3. Wrap Up&lt;/span&gt;&lt;br /&gt;cn.Close&lt;br /&gt;Set cn = Nothing&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE &lt;/b&gt;This has been a very basic exploration of how to employ the Insert, Update and Drop XMLA commands.&amp;nbsp; For more information on these, please check out &lt;/span&gt;&lt;/span&gt;&lt;a href="http://technet.microsoft.com/en-us/library/ms187188.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" face="Calibri" size="3" color="#0000ff"&gt;this entry in Books Online&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10331981" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Writeback to a Parent-Child Dimension</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/19/writeback-to-a-parent-child-dimension.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/07/19/writeback-to-a-parent-child-dimension.aspx</id><published>2012-07-20T00:45:00Z</published><updated>2012-07-20T00:45:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;&lt;span size="3"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt; &lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE &lt;/b&gt;This &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;is&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt; part of a series of entries on the topic of &lt;/span&gt;&lt;/span&gt;&lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" size="3" face="Calibri" color="#0000ff"&gt;Building Writeback Applications with Analysis Services&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Writeback to a parent-child dimension is handled using the ALTER CUBE MDX statement. This&amp;nbsp;statement&amp;nbsp;identifies the cube along with the operation to be performed.&amp;nbsp; While there are many operations that can be performed through the ALTER CUBE statement, we are interested in those allowing us to add, move and drop a dimension member.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE &lt;/b&gt;There full array of operations supported by the ALTER CUBE statement is something you may wish to explore if you are building an application against Analysis Services.&amp;nbsp; For a more complete survey of these operations, please check out &lt;/span&gt;&lt;/span&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms144822.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" size="3" face="Calibri" color="#0000ff"&gt;this Books Online entry&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Adding a Member&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To add a member to&amp;nbsp;a dimension, the CREATE DIMENSION MEMBER clause is used to identify the new member by name and by key (should the key and the name not be the same) and to specify the value of any additional properties associated with the new member.&amp;nbsp; In this sample, a new member, Objective A.X which sits under the parent member Objective A, is added to the Objective dimension&amp;rsquo;s Objectives parent-child hierarchy.&amp;nbsp; The member&amp;rsquo;s lone property, Owner, is assigned a value in the statement as well:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;ALTER CUBE [Project Scorecard]&lt;br /&gt; CREATE DIMENSION MEMBER &lt;br /&gt; &amp;nbsp;&amp;nbsp; [Objective].[Objectives].[Objective A].[Objective A.X], &lt;br /&gt; &amp;nbsp;&amp;nbsp; [Owner] =&amp;nbsp; "Owner 01";&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;As the key and the name for the Objective A.X member are the same, the key is not identified in the previous&amp;nbsp;statement.&amp;nbsp; However, the following statement, employing the Key keyword,&amp;nbsp;could&amp;nbsp;be issued to the same effect:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;ALTER CUBE [Project Scorecard]&lt;br /&gt; CREATE DIMENSION MEMBER &lt;br /&gt; &amp;nbsp;&amp;nbsp; [Objective].[Objectives].[Objective A].[Objective A.X],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Key =&amp;nbsp; "Objective A.X",&lt;br /&gt; &amp;nbsp;&amp;nbsp; [Owner] =&amp;nbsp; "Owner 01";&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Moving a Member&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To move a member to a new position within&amp;nbsp;a parent-child hierarchy, the MOVE DIMENSION MEMBER clause is employed to identify the member and its new parent.&amp;nbsp; In the following sample statement, the member Objective A.X is moved to a position immediately under member Objective B:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;ALTER CUBE [Project Scorecard]&lt;br /&gt; MOVE DIMENSION MEMBER&lt;br /&gt; &amp;nbsp;&amp;nbsp; [Objective].[Objectives].[Objective A.X]&lt;br /&gt; UNDER [Objective].[Objectives].[Objective B];&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;If you wish to skip levels between the new parent and the moved member, the SKIPPED_LEVELS keyword&amp;nbsp;can be employed along with a valid positive integer value.&amp;nbsp; If not specified, it is assumed that the new member resides just under its newly assigned&amp;nbsp;parent.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Please note, should the member being moved have descendants, those descendents are moved with it to the newly specified position.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Dropping a Member&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To drop a member, the DROP DIMENSION MEMBER clause is used, identifying the member to be removed.&amp;nbsp; The WITH DESCENDANTS&amp;nbsp;keyword phrase&amp;nbsp;can be&amp;nbsp;used to drop any descendant members of this member.&amp;nbsp; Without that subclause,&amp;nbsp;descendants of the dropped member are moved under the it's parent (retaining the&amp;nbsp;hierarchical structure of the descendants).&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In this sample, the Objective A.X member is dropped along with any potential descendants:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;ALTER CUBE [Project Scorecard] &lt;br /&gt; DROP DIMENSION MEMBER &lt;br /&gt; &amp;nbsp;&amp;nbsp; [Objective].[Objectives].[Objective A.X]&lt;br /&gt; WITH DESCENDANTS;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10331805" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Introducing Dimension Writeback</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/20/introducing-dimension-writeback.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/20/introducing-dimension-writeback.aspx</id><published>2012-06-20T21:07:00Z</published><updated>2012-06-20T21:07:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt; This is part of a series of entries on the topic of &lt;/span&gt;&lt;/span&gt;&lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" size="3" face="Calibri" color="#0000ff"&gt;Building Writeback Applications with Analysis Services&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Up to this point, we&amp;rsquo;ve focused exclusively on the update of measures using cell writeback.&amp;nbsp; When we need to insert, update or delete dimension records, a different form of writeback, &lt;i&gt;i.e.&lt;/i&gt; dimension writeback, is employed.&amp;nbsp; Far less frequently used than cell writeback, dimension writeback is a very useful technique when we need to give analysts control over dimension data.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE&lt;/b&gt; As a reminder, dimension writeback is not available in SQL Server Standard edition.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Like cell writeback, dimension writeback is performed by establishing an (ADO or ADO.NET using the MSOLAP provider)&amp;nbsp;connection to Analysis Services and submitting statements to affect the writeback operation.&amp;nbsp; However, there is no writeback cache with dimension writeback.&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Instead, the operation is performed immediately through Analysis Services and against the associated table (or updateable view)&amp;nbsp;in the relational database.&amp;nbsp; There is no separate step to discard (rollback) or publish (commit) the changes.&amp;nbsp;&amp;nbsp; In addition there is no inherent audit trail retained for the data changes and the operation must meet all the constraints imposed on the relational database table, &lt;i&gt;e.g.&lt;/i&gt; provide values for non-nullable fields, if the operation is to succeed.&amp;nbsp; In this regard, Analysis Services simply provides a consistent point of interaction for the writeback application.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE &lt;/b&gt;Permission to perform dimension writeback is often limited to a small subset of the application&amp;rsquo;s users.&amp;nbsp; In addition to meeting the security requirements of Analysis Services, the connection through which interactions with the underlying dimension table take place must have the permissions required to perform the associated DML operations within the relational database.&amp;nbsp; Without these permissions, an error will be generated in the relational database and surfaced through Analysis Services.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;From a structural perspective, a dimension supporting writeback must be mapped to a single table in the data source view.&amp;nbsp; That table should map to a single table or updateable view in the associated relational data source.&amp;nbsp; The dimension must also have its WriteEnabled property set to True, and users without full control of the Analysis Services &lt;/span&gt;&lt;/span&gt;&lt;span size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;database must be assigned Read/Write permission to the dimension through a role.&amp;nbsp; Then, depending on the type of dimension being written to, i.e. a parent-child or regular dimension, the application must submit either the ALTER CUBE MDX statement or one of three XMLA statements, respectively.&amp;nbsp; Writeback to parent-child and regular dimensions &lt;/span&gt;&lt;/span&gt;are addressed &lt;span size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;separately in the next&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt; two blog entries.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Finally, on the topic of security, end-users you wish to perform dimension writeback must be granted Read/Write permissions on the dimension(s) to which you wish to allow them to write.&amp;nbsp; This can be assigned to the dimension at the database level or to cube dimensions (at the cube level), though database-level rights make the most sense to me personally.&amp;nbsp; Users with Full Control Permission on a database and AS admins also have permission to write data (assuming the dimension other wise meets the requirements for this feature).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10322353" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Allocation across a Parent-Child Hierarchy</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/19/allocation-across-a-parent-child-hierarchy.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/19/allocation-across-a-parent-child-hierarchy.aspx</id><published>2012-06-19T21:31:00Z</published><updated>2012-06-19T21:31:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; This is part of a series of entries onthe topic of &lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building Writeback Applications with Analysis Services&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;A parent-child hierarchy consists of members with which values are associated at various levels.&amp;nbsp; A frequently cited example of such a hierarchy is the Employees hierarchy of an Employee dimension.&amp;nbsp; Applied to a Salary measure, members up and down the hierarchy are associated with values.&amp;nbsp; For managers, the associated salary value reflects not only that individual&amp;rsquo;s salary those of any subordinate members.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Times New Roman; font-size: small;" size="3" face="Times New Roman"&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To differentiate between that part of the measure value that is directly attributable to the member and that which represents an aggregate of its subordinates, Analysis Services injects a special (leaf-level) member, the Member with Data member, directly under each member of the parent-child hierarchy.&amp;nbsp; The Member with Data member holds the directly attributable portion of the value, leaving the member with which it is associated to present the aggregate of the Member with Data member and any of its other subordinates. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;By default, the Member with Data member is not visible in a parent-child hierarchy but this can be changed through the hierarchy&amp;rsquo;s MembersWithData property setting.&amp;nbsp; Visible or not, the Member with Data member is always present so that when data is written back to a member of a parent-child hierarchy, the Members With Data member is considered for allocation.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To illustrate the consequence of this, let&amp;rsquo;s say Lisa is a member of the Employees parent-child hierarchy and has two subordinates, John and Jane, neither of which has subordinates of their own.&amp;nbsp; If we writeback a value of $150,000 to the Lisa member and use the default equal allocation (USE_EQUAL_ALLOCATION) technique, John and Jane each reflect $50,000 and Lisa reflects the $150,000 we wrote.&amp;nbsp; The missing $50,000 has been assigned to Lisa&amp;rsquo;s Member with Data member.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;If this is what we intended with the writeback, then great!&amp;nbsp; But if it&amp;rsquo;s not what we intended, how else might we approach this problem?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;First, we could write back only to members with no other subordinates other than their Member with Data member.&amp;nbsp; If values need to be written up and down the hierarchy, this might require you to expose the Member with Data member through the MembersWithData property setting.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Alternatively, we might write back to the attribute hierarchy upon which the parent-child hierarchy is based.&amp;nbsp; (For example, the Employees parent-child hierarchy is based on an Employee attribute hierarchy so that we might write back to it instead.)&amp;nbsp; This works so long as navigation of the attribute-hierarchy is not problematic. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Finally, you might allow write back to any member in a parent-child hierarchy and take explicit control of the allocation process using a weighting expression.&amp;nbsp; In the expression, you might identify the Member with Data member using the DATAMEMBER function.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Of course, there&amp;rsquo;s always the option of not using a parent-child hierarchy in your cube design and avoiding this complication altogether.&amp;nbsp; However, parent-child hierarchies are very flexible making them ideal for performing dimension writeback, a topic I will present in the next few blog entries.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10321950" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Understanding Allocations</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/16/understanding-allocations.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/16/understanding-allocations.aspx</id><published>2012-06-16T20:18:00Z</published><updated>2012-06-16T20:18:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt; This is part of a series of entries on the topic of &lt;/span&gt;&lt;/span&gt;&lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;&lt;span style="color: #0000ff; font-family: Calibri; font-size: small;" face="Calibri" size="3" color="#0000ff"&gt;Building Writeback Applications with Analysis Services&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" face="Times New Roman" size="3"&gt; &lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;In my previous entries on this topic, I&amp;rsquo;ve been writing data to the Score measure at the intersection of an individual project and a leaf-level objective.&amp;nbsp; The value that is being written represents data at the finest level of granularity supported in the cube as no dimension members within the Project or Objective dimensions rolls up into that value.&amp;nbsp; We might describe this as writing at the leaf-level as I am working with only leaf-level members across all my related dimensions.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;By working at the leaf-level, I&amp;rsquo;ve avoided the complexity of allocation.&amp;nbsp; Allocation occurs when a value is written above the leaf-level.&amp;nbsp; For example, if I were to write a score for the All Projects member of the Project dimension, Analysis Services would need instruction on how to allocate that score across the leaf-level projects in the cube.&amp;nbsp; &amp;nbsp;Regardless of the level at which you write data, Analysis Services always allocates your value to the leaf-level and then aggregates the value back up.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To consider how Analysis Services goes about this, let&amp;rsquo;s use a very simple cube.&amp;nbsp; In this cube, we are focused on forecasting sales of products.&amp;nbsp; There is one dimension, Product, and it has two attributes, Product Category and Product Subcategory, the latter of which rolls up into the former. &amp;nbsp;In the cube&amp;rsquo;s one measure group, we have two measures, Sales (Amount) and Quantity, both of which aggregate by simple summation.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" face="Times New Roman" size="3"&gt; &lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/5822.image1.png"&gt;&lt;img width="280" height="158" style="margin-right: auto; margin-left: auto; display: block;" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/5822.image1.png" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;Let&amp;rsquo;s say that from a previous forecasting exercise, Sales for Subcategory A.1 was expected to be $180 and Subcategory A.2 was expected to be $20 giving us forecasted sales of $200 for Category A.&amp;nbsp; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;Two-hundred dollars seems a bit low for Category A so we write a value of $300 to its Sales measure.&amp;nbsp; What should be the new Sales Amount values for subcategories A.1 and A.2?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" face="Times New Roman" size="3"&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/1513.image-2.png"&gt;&lt;img width="333" height="111" style="margin-right: auto; margin-left: auto; display: block;" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/1513.image-2.png" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Analysis Services provides you four options for handling this.&amp;nbsp; These options represent the intersection of the answers to two simple questions:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;What would you like to allocate?&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;How would you like to allocate it?&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The answer to the question of what to allocate is either the value you wrote or the difference between that value the previous value.&amp;nbsp; In our sales forecast example, the value is $300 and the increment &amp;ndash; the difference between the new value and the previous value &amp;ndash; is $100. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Using either the value or the increment, we now consider how to allocate it. Here we have two options.&amp;nbsp; We can evenly divide the value or increment evenly across the leaf-level members under us &amp;ndash; in our case that would be subcategories A.1 and A.2.&amp;nbsp; Or, we can employ a weighting expression to determine which proportion of the value or increment is applied to each leaf member. (This is referred to as weighted allocation.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE&lt;/b&gt; I&amp;rsquo;m saying &amp;ldquo;leaf-level member&amp;rdquo; as I think it&amp;rsquo;s the easiest for most folks to digest but in reality Analysis Services is considering the leaf-level tuples that aggregate to the tuple to which we are writing.&amp;nbsp; For the very, very simple cube we are using, the two phrases are highly interchangeable.&amp;nbsp; For more complex cubes, understanding the difference in these concepts might be helpful.&amp;nbsp; But then again, that&amp;rsquo;s probably more technical than most folks need.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The weighting expression is certainly the more complex of these two options but it gives you far more control over the allocation process.&amp;nbsp; The expression is an MDX expression that is evaluated for each leaf-level member. Typically, the weighting expression is calculated as a ratio between 0 and 1 and the sum of all of its evaluations across the leaf-level entries sums to 1.&amp;nbsp; However, neither of these constraints is enforced.&amp;nbsp; This gives you maximum flexibility but also means you need to carefully consider (and validate) your weighting expressions.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;The default weighting expression (when weighted allocation is employed but no expression is provided) performs a proportional allocation based on the leaf-level member&amp;rsquo;s contribution to the original value that is now being overwritten.&amp;nbsp; In our sales example, a proportional allocation would assign 0.90 as the weighting value to Subcategory A.1 as that subcategory&amp;rsquo;s value of $180 represents 90% of Category A&amp;rsquo;s value of $200.&amp;nbsp; Similarly, Subcategory A.2 would be assigned a weighting value of 0.10.&amp;nbsp; An equivalent weighting expression would look something like this:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p align="center"&gt;([Measures].[Sales], [Product].[Product Subcategory].CurrentMember) / &lt;br /&gt;([Measures].[Sales], [Product].[Product Category].CurrentMember)&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE &lt;/b&gt;There are so many ways you can write this expression, and I have purposefully added otherwise unnecessary elements in order to give is a bit more clarity.&amp;nbsp; (If you are new to MDX, clarity is relative, eh?)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Getting back to the questions of what to allocate and how to allocate it, you can now see how we arrive at Analysis Service&amp;rsquo;s four options for handling allocation.&amp;nbsp; The keyword controlling the allocation behavior is presented in the chart below.&amp;nbsp; This keyword is tacked onto the end of the UPDATE CUBE statement (followed by the weighting expression if one of the weighted options is employed and other than a proportional allocation is desired).&amp;nbsp; If no keyword is provided and allocation must be performed, Analysis Services uses the &lt;/span&gt;USE_EQUAL_ALLOCATION&lt;span style="font-family: Calibri;" face="Calibri"&gt; option which allocates the value equally amongst the leaves.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" face="Times New Roman" size="3"&gt; &lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/4276.image-3.png"&gt;&lt;img style="margin-right: auto; margin-left: auto; display: block;" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/4276.image-3.png" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Times New Roman; font-size: small;" face="Times New Roman" size="3"&gt;&lt;span style="font-family: Times New Roman; font-size: small;" face="Times New Roman" size="3"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To ensure these four options are crystal clear, let&amp;rsquo;s return one last time to the sales forecast example. We had an original value of $200 for the Category A sales which was the sum of $180 for Subcategory A.1 and $20 for Subcategory A.2.&amp;nbsp; We then updated the sales for Category A from $200 to $300.&amp;nbsp; That gives us a new value of $300 and an increment of $100.&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;If we perform an even allocation of the value (&lt;/span&gt;USE_EQUAL_ALLOCATION&lt;span style="font-family: Calibri;" face="Calibri"&gt;), Subcategory A.1 becomes $150 ($300/2 leaves) and Subcategory A.2 becomes $150 ($300/2 leaves).&amp;nbsp; If we perform an even allocation of the increment (&lt;/span&gt;USE_EQUAL_INCREMENT&lt;span style="font-family: Calibri;" face="Calibri"&gt;), Subcategory A.1 becomes $230 ($180 + $100/2 leaves) and Subcategory A.2 becomes $70 ($20 + $100/2 leaves).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;If we perform a weighted allocation of the value (&lt;/span&gt;USE_WEIGHTED_ALLOCATION&lt;span style="font-family: Calibri;" face="Calibri"&gt;) and use the default weighting expression, Subcategory A.1 becomes $270 ($300 * $180/$200) and Subcategory A.2 becomes $30 ($300 * $20/$200).&amp;nbsp; If we perform a weighted allocation of the increment (&lt;/span&gt;USE_WEIGHTED_INCREMENT&lt;span style="font-family: Calibri;" face="Calibri"&gt;) and again use the default weighting expression, Subcategory A.1 becomes $270 ($180 + $100 * $180/$200) and Subcategory A.2 becomes $30 ($20 + $100 * $20/$200).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE&lt;/b&gt; When the default weighting expression is used, the resulting values are the same even though they are derived using differing logic.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Before leaving the topic of allocations, there are three final items I need to briefly address.&amp;nbsp; First, allocation always occurs at the leaf-level and is aggregated back up.&amp;nbsp; As a result, there can be an accumulation of rounding errors which cause you to get back a value slightly different from the one you wrote.&amp;nbsp; If this is a problem, consider writing to the leaf-levels yourself where you can have explicit control of your values.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Second, some older documentation on allocation in Analysis Services highlights a &lt;/span&gt;NO_ALLOCATION&lt;span style="font-family: Calibri;" face="Calibri"&gt; option.&amp;nbsp; I&amp;rsquo;m not sure the story behind it but please be aware there is no such supported option.&amp;nbsp; Some folks say it is accepted in older versions but doesn&amp;rsquo;t do what&amp;rsquo;s expected and others say it causes an error to be returned.&amp;nbsp; Either way, don&amp;rsquo;t use this.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Finally, the &lt;/span&gt;Update Isolation Level&lt;span style="font-family: Calibri;" face="Calibri"&gt; connection string parameter can be used to improve Analysis Service&amp;rsquo;s performance during allocation.&amp;nbsp; That said, don&amp;rsquo;t use it unless you really need it and only use it if you fully understand its impact.&amp;nbsp; I might write a longer entry on this parameter in the future, but for now here&amp;rsquo;s the short version: setting this parameter to 1 tells Analysis Services that there is no overlap between the cells impacted by allocation in a single UPDATE CUBE statement.&amp;nbsp; This allows Analysis Services to skip some steps it might otherwise perform (which boosts performance). But these steps are also used to ensure you get the right values back from the cube so again don&amp;rsquo;t use this unless you really need it and you fully understand it.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;NOTE &lt;/b&gt;There really is a fourth thing I need to address, and that&amp;rsquo;s around a special leaf-level member in a parent-child hierarchy and how it is handled during allocation.&amp;nbsp; But that&amp;rsquo;s a topic for another entry.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10321006" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Sidebar: The MS IT Pattern for Custom Writeback Applications</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/05/sidebar-the-ms-it-pattern-for-custom-writeback-applications.aspx" /><link rel="enclosure" type="application/zip" length="41177" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-31-52-49/Custom-Cell-Writeback.zip" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/05/sidebar-the-ms-it-pattern-for-custom-writeback-applications.aspx</id><published>2012-06-05T14:27:00Z</published><updated>2012-06-05T14:27:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; This is part of a series of entries on the topic of &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building a Writeback Application with Analysis Services&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Writeback to cubes through Excel applications is used extensively within Microsoft to support a number of our internal processes, including our mid-year business review.&amp;nbsp; Sergei Gundorov and Pablo Trejo Montemayor with MS IT outline how writeback fits into this process within &lt;a href="http://technet.microsoft.com/en-us/library/gg191725.aspx"&gt;this white paper&lt;/a&gt;. &amp;nbsp;It&amp;rsquo;s well worth a read.&lt;/p&gt;
&lt;p&gt;As you might imagine, supporting a custom application written in Excel within a company the size of Microsoft can be challenging.&amp;nbsp; To address this, Sergei and Pablo have focused on standardizing the implementation of the writeback code and extending the capabilities of Excel Services in SharePoint to manage the code base.&amp;nbsp; And they do this in a manner that retains the flexibility that drives most analysts to employ Excel.&amp;nbsp; Check out these white papers to explore the details of what they are doing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/gg521158.aspx"&gt;Enabling Write-back to an OLAP Cube at Cell Level in Excel 2010&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/cc540662(v=office.12).aspx"&gt;Creating Business Applications by Using Excel Services and Office Open XML Formats&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Focusing on the Excel application aspects of what Sergei and Pablo are doing, the process in a nutshell is to use the &lt;a href="http://office.microsoft.com/en-us/excel-help/cube-functions-reference-HA010083026.aspx"&gt;Excel cube functions&lt;/a&gt; to retrieve data from a cube, have users enter data in associated Excel cells, use a custom function to evaluate the user&amp;rsquo;s input, and then pull all the valid data input together to form an UPDATE CUBE statement that is then submitted and committed to Analysis Services.&amp;nbsp; &amp;nbsp;If you are just getting started with Excel cube functions, you might find that starting with a PivotTable containing the data you want and then &lt;a href="http://office.microsoft.com/en-us/excel-help/convert-pivottable-cells-to-worksheet-formulas-HA010096303.aspx#BM2"&gt;converting the PivotTable to formulas&lt;/a&gt; (based on cube functions) is the easiest way to go.&amp;nbsp; If you&amp;rsquo;d like to review a working demo that incorporates Sergei and Pablo&amp;rsquo;s code and follows the basic Excel pattern, please check out the sample macro-enabled workbook associated with this entry.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10315249" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Building a Custom Writeback Application</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/04/building-a-custom-writeback-application.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/04/building-a-custom-writeback-application.aspx</id><published>2012-06-05T01:09:00Z</published><updated>2012-06-05T01:09:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; This is part of a series of entries on the topic of &lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building Writeback Applications with Analysis Services&lt;/a&gt;.&amp;nbsp; If you have not read the other posts in this series, you will want to read &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-technical-review-of-the-simple-demonstration.aspx"&gt;A Technical Review of the Simple Demonstration&lt;/a&gt; before proceeding.&lt;/p&gt;
&lt;p&gt;Once you have a &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-write-enabled-cube.aspx"&gt;write-enabled cube&lt;/a&gt; in place, you then need a writeback application to interact with it.&amp;nbsp; As shown in an earlier demonstration, Excel 2010 has writeback functionality built into its PivotTable feature.&amp;nbsp; However, if you need another means to interact with your cube, you can build a custom writeback application by following a relatively simple pattern.&lt;/p&gt;
&lt;p&gt;The pattern consists of connecting to the Analysis Services cube, issuing statements to update the cube, and then committing or rollingback these updates.&amp;nbsp; Yes, there are other parts to this such as the retrieval and presentation of the data, the handling of data entry, etc. but those are presentation details I&amp;rsquo;ll assume most application developers are familiar with. (That said, I will address a few presentation details in my next post highlighting a pattern used by Microsoft IT for building writeback applications within our company.)&lt;/p&gt;
&lt;p&gt;To establish a connection to Analysis Services, use a standard library such as ADO or ADO.Net.&amp;nbsp; Analysis Management Objects (AMO) and ADOMD can also be used but these build off of ADO.NET and don&amp;rsquo;t really add much in the context of most writeback applications.&lt;/p&gt;
&lt;p&gt;Minimally, the connection string employed should specify the MSOLAP provider and identify the Analysis Services instance and database. &amp;nbsp;Here is a sample connection string that gets the job done:&lt;/p&gt;
&lt;p align="center"&gt;&lt;span style="font-family: courier new,courier;"&gt;Provider=MSOLAP;Data Source=localhost;Initial Catalog=Writeback Demo;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE &lt;/b&gt;Once the connection is established, don&amp;rsquo;t close it until you are ready to commit or rollback your updates.&amp;nbsp;Closing the connection will cause the writeback cache to be discarded, effectively rolling back any outstanding transactions.&lt;/p&gt;
&lt;p&gt;With the connection established, you can initialize the writeback cache by issuing a BEGIN TRANSACTION statement.&amp;nbsp; Excel 2010&amp;rsquo;s PivotTable does this but it&amp;rsquo;s not actually necessary. If you don&amp;rsquo;t initialize the cache explicitly, an implicit transaction is created with your first data update.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; If you are familiar with Transact-SQL (T-SQL), you probably know you can manage transactions using BEGIN TRAN, COMMIT TRAN, and ROLLBACK TRAN or BEGIN TRANSACTION, COMMIT TRANSACTION, and ROLLBACK TRANSACTION.&amp;nbsp; The MDX language used by Analysis Services does not accept the shortened form of the transaction keyword. You have to spell it out in full or you will receive an error.&lt;/p&gt;
&lt;p&gt;Updates are submitted over the connection using the &lt;a href="http://msdn.microsoft.com/en-us/library/ms145488.aspx"&gt;UPDATE CUBE statement&lt;/a&gt;. The statement is pretty straightforward in that you identify the cube you wish to update and assign values one or more tuples (cells) in a comma-delimited list.&amp;nbsp; If you are assigning values to a nonleaf tuple, you can identify an allocation method as the last part of the statement.&amp;nbsp; (I&amp;rsquo;ll cover allocation in much more depth in a later post.)&amp;nbsp;&amp;nbsp; Here is a sample UPDATE CUBE statement that assigns values to two leaf-level tuples:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;UPDATE CUBE [Project Scorecard] &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;SET&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; (&lt;br /&gt;&amp;nbsp;&amp;nbsp; [Project].[Project].[Project 01], &lt;br /&gt;&amp;nbsp;&amp;nbsp; [Objective].[Objectives].[Objective A.1],&lt;br /&gt;&amp;nbsp;&amp;nbsp; [Measures].[Score]) = 5,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; (&lt;br /&gt;&amp;nbsp;&amp;nbsp; [Project].[Project].[Project 01], &lt;br /&gt;&amp;nbsp;&amp;nbsp; [Objective].[Objectives].[Objective A.2],&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; [Measures].[Score]) = 3;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Whether you explicitly initiated a transaction or allowed the UPDATE CUBE statement to implicitly create one for you, the final step to the writeback application pattern is to either commit or rollback that transaction.&amp;nbsp; Committing the transaction with the COMMIT TRANSACTION statement forces Analysis Services to write the writeback cache to the writeback partition (table) created at cube design time.&amp;nbsp; If the writeback table is not accessible due to either the relational database being offline or a permissions issue, an error will be generated. &amp;nbsp;To roll back the transaction, the ROLLBACK TRANSACTION statement can be used or the connection to Analysis Services can simply be broken.&lt;/p&gt;
&lt;p&gt;The following VBA code sample puts this all together for us.&amp;nbsp; Why VBA, you ask? Because most writeback applications are written as Office applications.&amp;nbsp; Keep in mind that most writeback applications are targeted at a small set of (typically expert) users for whom Office is preferred and VBA is familiar.&amp;nbsp; Here&amp;rsquo;s the code sample:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'Add reference to Microsoft ActiveX Data Objects 6.0 Library&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'Update Statement to Submit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; UpdateStatement &lt;span style="color: #0000ff;"&gt;As String&lt;/span&gt; = _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #ff0000;"&gt;"update cube [Project Scorecard] "&lt;/span&gt; + _&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #ff0000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "set ([Project].[Project].[Project 01]," &lt;span style="color: #000000;"&gt;+ _&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "[Objective].[Objectives].[Objective A.1]," &lt;span style="color: #000000;"&gt;+ _&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "[Measures].[Score])=4&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #ff0000; font-family: courier new,courier;"&gt;;"&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; CommitStatement &lt;span style="color: #0000ff;"&gt;As String&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"commit transaction;"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'1. Establish Connection to Analysis Services Database&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; cn &lt;span style="color: #0000ff;"&gt;As New&lt;/span&gt; ADODB.Connection&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Open &lt;span style="color: #ff0000;"&gt;"Provider=MSOLAP;Data Source=localhost;Initial Catalog=Writeback Demo;"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'2. Execute Command &amp;amp; Commit Transaction&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Execute UpdateStatement&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Execute CommitStatement&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'3. Wrap Up&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Close&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Set&lt;/span&gt; cn = &lt;span style="color: #0000ff;"&gt;Nothing&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To make this a bit more interesting, here is a variant of this pattern using VB.NET, ADO.NET and the Command object:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'Update Statement to Submit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; UpdateStatement &lt;span style="color: #0000ff;"&gt;As String&lt;/span&gt; =&lt;span style="color: #ff0000;"&gt; "update cube [Project Scorecard] "&lt;/span&gt; + _&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #ff0000; font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "set ([Project].[Project].[Project 01]," &lt;span style="color: #000000;"&gt;+ _&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "[Objective].[Objectives].[Objective A.1],[Measures].[Score])=4;"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; CommitStatement &lt;span style="color: #0000ff;"&gt;As String&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;&amp;ldquo;commit transaction;"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'1. Establish Connection to Analysis Services Database&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; cnstr &lt;span style="color: #0000ff;"&gt;As String&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"Provider=MSOLAP;Data Source=localhost;Initial Catalog=Writeback Demo;"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; cn &lt;span style="color: #0000ff;"&gt;As New&lt;/span&gt; Data.OleDb.&lt;span style="color: #0000ff;"&gt;OleDbConnection&lt;/span&gt;(cnstr)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Open()&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'2.Set Up Command&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;Dim cmd As Data.OleDb.&lt;span style="color: #0000ff;"&gt;OleDbCommand&lt;/span&gt; = cn.CreateCommand&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.CommandType = &lt;span style="color: #0000ff;"&gt;CommandType&lt;/span&gt;.Text&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'3. Execute Command &amp;amp; Commit Transaction&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.CommandText = UpdateStatement&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.ExecuteNonQuery()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.CommandText = CommitStatement&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.ExecuteNonQuery()&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'4. Wrap Up&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Close()&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And here is a final variant, again using VB.NET, ADO.NET and the Transaction object.&amp;nbsp; The Transaction object doesn&amp;rsquo;t really add much to the sample but I&amp;rsquo;ve put it here for completeness:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'Update Statement to Submit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; UpdateStatement &lt;span style="color: #0000ff;"&gt;As String&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"update cube [Project Scorecard] "&lt;/span&gt; + _&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #ff0000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "set ([Project].[Project].[Project 01],"&lt;/span&gt; + _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #ff0000;"&gt;"[Objective].[Objectives].[Objective A.1],[Measures].[Score])=4;"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'1. Establish Connection to Analysis Services Database&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; cnstr &lt;span style="color: #0000ff;"&gt;As String&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"Provider=MSOLAP;Data Source=localhost;Initial Catalog=Writeback Demo;"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; cn &lt;span style="color: #0000ff;"&gt;As New&lt;/span&gt; Data.OleDb.&lt;span style="color: #0000ff;"&gt;OleDbConnection&lt;/span&gt;(cnstr)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Open()&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'2. Set Up Command &amp;amp; Its Transaction&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; trn &lt;span style="color: #0000ff;"&gt;As&lt;/span&gt; Data.OleDb.&lt;span style="color: #0000ff;"&gt;OleDbTransaction&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&lt;span style="color: #0000ff;"&gt;Dim&lt;/span&gt; cmd &lt;span style="color: #0000ff;"&gt;As&lt;/span&gt; Data.OleDb.&lt;span style="color: #0000ff;"&gt;OleDbCommand&lt;/span&gt; = cn.CreateCommand&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.CommandType = &lt;span style="color: #0000ff;"&gt;CommandType&lt;/span&gt;.Text&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.CommandText = UpdateStatement&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'3. Execute Command &amp;amp; Commit Transaction&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;trn = cn.BeginTransaction()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.Transaction = trn&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cmd.ExecuteNonQuery()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;trn.Commit()&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #008000; font-family: courier new,courier;"&gt;'4. Wrap Up&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;cn.Close()&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10314967" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Building a Write-Enabled Cube</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-write-enabled-cube.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-write-enabled-cube.aspx</id><published>2012-06-04T04:49:00Z</published><updated>2012-06-04T04:49:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; This is part of a series of entries on the topic of &lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building Writeback Applications with Analysis Services&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To build a writeback application, you need a write-enabled cube and an application with which to interact with it.&amp;nbsp; I&amp;rsquo;ll cover the application in my next post, but for now I&amp;rsquo;ll focus on the cube.&lt;/p&gt;
&lt;p&gt;The design of the cube depends on the model you wish to employ.&amp;nbsp;The key thing to keep in mind is that the concerns about data volumes, scalability, maintenance and processing cycles we typically weigh when designing a cube do not come into play as much with a write-enabled cube.&amp;nbsp; The write-enabled cube is often of limited scope, receives smaller and less regular data updates, and is used by smaller numbers of more specialized (often expert) users.&amp;nbsp; These cubes are sometimes mapped to a data warehouse but more frequently are built against a specialized data mart.&amp;nbsp; There are always exceptions but the point I want to drive home is that you are not typically injecting writeback into the middle of a traditionally built OLAP cube.&lt;/p&gt;
&lt;p&gt;As a cube designer, the key thing to concern yourself with are the limitations imposed on the measures and measure groups of a write-enabled cube.&amp;nbsp; Any measure to which you wish to writeback data must be mapped to values in the data source view, &lt;i&gt;i.e.&lt;/i&gt; not calculated members defined in the cube script.&amp;nbsp; These measures must employ signed&amp;nbsp;numeric data types and use the SUM aggregation function.&amp;nbsp; And, the measure group housing a writeback measure must employ regular relationships only.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Thinking back to the cube in the &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-simple-demonstration-of-what-if-analysis.aspx"&gt;simple demonstration&lt;/a&gt;, you may be curious how these restrictions were overcome.&amp;nbsp; The cube seemed to employ a many-to-many relationship between the measure group housing the Score measure and the Scenario dimension and the Score measure itself employed a weighted average for aggregate values.&amp;nbsp; All this was handled with a little sleight-of-hand in the cube script.&amp;nbsp; While not a requirement, write-enabled cubes tend to make very heavy use of the cube script to both work around the limitations imposed on the cube and implement the model&amp;rsquo;s calculation logic.&lt;/p&gt;
&lt;p&gt;Returning to the writeback measure, if you intend to commit (publish) data the limitations on the writeback measure apply to all measures in its measure group.&amp;nbsp; To clarify, if you only intend to have users perform writeback on a measure and then discard their changes, measures in the same measure group as the measure to which the user is writing do not have to follow the rules above.&amp;nbsp; However, if you wish to commit the data (which is the much more typical case) ever measure in the group must adhere to these rules, regardless of whether they receive writeback modification.&lt;/p&gt;
&lt;p&gt;To house the committed writeback data for the measure group, you must setup a writeback partition per &lt;a href="http://msdn.microsoft.com/en-us/library/ms175664(v=SQL.90).aspx"&gt;these instructions&lt;/a&gt;.&amp;nbsp; This creates a writeback table in a relational database for which you have established a data source connection.&amp;nbsp; (This is typically the same source to which the measure group is mapped, but you have flexibility should you need it.)&amp;nbsp; Keep in mind that the account used with the data source must have the permissions required to create this table when the cube is published and read and write permissions to it once it is deployed.&lt;/p&gt;
&lt;p&gt;On the topic of security, any end-users you wish to perform writeback to the cube must be granted Read/Write permissions at the cube level.&amp;nbsp;By setting read/write permissions on the cell data, you can more narrowly define to which cells a user can write.&amp;nbsp; Users with Full Control Permission on the&amp;nbsp;database and Analysis Services administrators also have read and write permissions across the cube.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10314530" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>A Technical Review of the Simple Demonstration</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-technical-review-of-the-simple-demonstration.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-technical-review-of-the-simple-demonstration.aspx</id><published>2012-06-03T19:10:00Z</published><updated>2012-06-03T19:10:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; This is part of a series of entries on the topic of &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building a Writeback Application with Analysis Services&lt;/a&gt;&amp;nbsp;and makes direct reference to a previous post containing &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-simple-demonstration-of-what-if-analysis.aspx"&gt;a simple demostration of what-if analysis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the simple demonstration of writeback, the analyst connected to a write-enabled cube, assembled a PivotTable, write-enabled the PivotTable, entered data and recalculated the cube, and then either published or discarded his or her changes.&amp;nbsp; Each of these steps represents an interaction with Analysis Services that&amp;rsquo;s important to understand.&lt;/p&gt;
&lt;p&gt;The connection to the write-enabled cube was established like any other connection to Analysis Services from Excel.&amp;nbsp; In fact, the OLE DB provider used by Excel to make the connection has only one parameter relevant to a writeback scenario, but it is optional and was not employed for this demonstration.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; I&amp;rsquo;ll point out that parameter in a later blog entry on allocations.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The analyst then assembled a PivotTable based on Analysis Services data.&amp;nbsp; As with establishing the connection, there is nothing special or different about this interaction.&lt;/p&gt;
&lt;p&gt;But then the analyst selected the option to write-enable the PivotTable.&amp;nbsp;That instructed Excel to unlocked the PivotTable for data entry and caused a BEGIN TRANSACTION (MDX) statement to be submitted to Analysis Services.&amp;nbsp; Now things are different.&amp;nbsp; The BEGIN TRANSACTION&amp;nbsp; statement causes Analysis Services to initialize an in-memory cache associated with the analyst&amp;rsquo;s connection.&lt;/p&gt;
&lt;p&gt;The analyst now enters values into the PivotTable and requests for it to be recalculated. &amp;nbsp;To recalculate the data in the PivotTable based on the data entered, an UPDATE CUBE statement containing these values is submitted to Analysis Services by the application.&amp;nbsp; Analysis Services calculates the difference between its values and the assignments in the UPDATE CUBE statement and writes these to the connection-specific writeback cache.&lt;/p&gt;
&lt;p&gt;While subsequent requests for data through this connection reflect the values in the writeback cache, the base cube remains unaltered.&amp;nbsp; Other analysts can interact with the cube without awareness of these updates, providing the analyst the freedom to explore a wide range of values without interfering with others&amp;rsquo; work.&lt;/p&gt;
&lt;p&gt;When the analyst is done with his or her work, he or she must then decide what to do with the values written back to the cube.&amp;nbsp; If the analyst decides to discard the changes, a ROLLBACK TRANSACTION statement is submitted which causes the cache to be reset.&amp;nbsp; (Alternatively, the analyst could simple break the connection to Analysis Services and the cache would be discarded.)&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If the analyst decides to publish the changes, a COMMIT TRANSACTION statement is submitted to Analysis Services which causes the data to be written to a writeback partition and to be reflected in data presented to all consumers of the cube. The writeback partition is established by the cube designer and houses the former contents of the writeback cache. It also associates date-time and user-identity values with the data to provide a basic audit trail.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10314425" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Sidebar: The Other What-If Analysis Options in Excel</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/sidebar-the-other-what-if-analysis-options-in-excel.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/sidebar-the-other-what-if-analysis-options-in-excel.aspx</id><published>2012-06-03T19:07:00Z</published><updated>2012-06-03T19:07:00Z</updated><content type="html">&lt;p style="text-align: left; padding-left: 30px;" align="center"&gt;&lt;b&gt;NOTE&lt;/b&gt; This is part of a series of entries on the topic of &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building a Writeback Application with Analysis Services&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What-if analysis against Analysis Services is just one form of what-if analysis supported by Excel.&amp;nbsp;Other forms focus on spreadsheet-based models and are exposed on the Data tab.&amp;nbsp; More information on these alternatives is found &lt;a href="http://office.microsoft.com/en-us/excel-help/introduction-to-what-if-analysis-HA010342628.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; Just to make things a bit more confusing, Excel can support even more forms of what-if analysis using the Solver add-in.&lt;/p&gt;
&lt;p&gt;The basic pattern of all these what-if analyses is the same.&amp;nbsp; The analyst constructs a model, varies inputs, and evaluates the outputs.&amp;nbsp;The fundamental difference is the type of model used: a spreadsheet or an Analysis Services cube.&lt;/p&gt;
&lt;p&gt;The question then becomes, Which model should I use for my analyses? In my opinion (and I&amp;rsquo;m by no means authoritative on this), Analysis Services is the right choice when the model is based on sets of related data with complex calculations across these.&lt;/p&gt;
&lt;p&gt;In addition, Analysis Services writeback supports:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Data input from multiple analysts,&lt;/li&gt;
&lt;li&gt;An audit trail of data input,&lt;/li&gt;
&lt;li&gt;Preservation of data input between analyses,&lt;/li&gt;
&lt;li&gt;Complex security for controlling the reading and writing of data&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of course, the use of Analysis Services as the model behind the analysis requires a moderate level of cube development skill within your organization. Other techniques (such as writing to a relational database which employ a more ubiquitous skillset) can be employed to address many of the previously stated requirements.&amp;nbsp; Still, Analysis Services (and OLAP in general) is unparalleled in its ability to express complex calculations which is why many planning, forecasting, and budgeting applications employ OLAP.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10314423" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>A Simple Demonstration of What-If Analysis</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-simple-demonstration-of-what-if-analysis.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-simple-demonstration-of-what-if-analysis.aspx</id><published>2012-06-03T16:46:00Z</published><updated>2012-06-03T16:46:00Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; This is the second of a series of entries on the topic of &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building a Writeback Application with Analysis Services&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To demonstrate writeback with Analysis Services, I&amp;rsquo;ll leverage a simple model built around a project selection process that takes place within a fictional company.&amp;nbsp;Through this process, projects are submitted from across the organization by a variety of users making writeback (with its associated audit trail which I&amp;rsquo;ll discuss in later entries) very appealing. However, the true driver behind the use of writeback is the need to evaluate uncertainty surrounding the organization&amp;rsquo;s objectives.&lt;/p&gt;
&lt;p&gt;Projects are submitted as part of a mid-year planning cycle.&amp;nbsp; At this point in the year, it&amp;rsquo;s always a bit unclear exactly what the organization&amp;rsquo;s priorities will be at the start of the next year.&amp;nbsp; If revenue targets are off, the company may enter the year focused on cost-cutting.&amp;nbsp; Alternatively, the company may find itself responding to changes in regulations, facing new competitive pressures, or seeking new opportunities for growth.&amp;nbsp; As there simply aren&amp;rsquo;t enough resources to address all the requested projects, the business needs a way to prioritize them in the face of this uncertainty.&lt;/p&gt;
&lt;p&gt;To deal with this uncertainty, projects are scored against a wide range of objectives.&amp;nbsp; Scenarios are created which reflect different potential areas of focus within the company in the next year, and objectives are weighted relative to their importance within each scenario.&amp;nbsp; Average project scores reflecting these weights can then be calculated so that decision makers can quickly determine which projects should receive priority under different circumstances.&amp;nbsp; Astute project sponsors might also consider how their projects might fare better or worse under a variety of likely scenarios with some minor adjustments. (A review process keeps everyone&amp;rsquo;s scores honest.)&lt;/p&gt;
&lt;p&gt;To support this, an Analysis Services cube is developed which relates scores to projects and objectives and weighs objectives under differing scenarios.&amp;nbsp; The following is a diagram of this model:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/3821.diagram1.png"&gt;&lt;img style="margin-right: auto; margin-left: auto; display: block;" border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/3821.diagram1.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To interact with this model, the analyst launches Excel 2010 (which has built-in writeback capabilities) and connects to the Analysis Services cube. A PivotTable is then constructed showing scores for Project 01 relative to various objectives under Scenario 1. Scenario 1 provides an even weighting to all the objectives allowing the user to concentrate on data entry.&amp;nbsp; The following illustrates the results of the analyst&amp;rsquo;s work:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/7142.image1.png"&gt;&lt;img style="margin-right: auto; margin-left: auto; display: block;" border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/7142.image1.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; I will not be covering the basics of connecting to Analysis Services from Excel and assembling a PivotTable and Slicers.&amp;nbsp; If you would like more information on these topics, please review &lt;a href="http://technet.microsoft.com/en-us/library/hh344830.aspx"&gt;this document&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To enable writeback, the analyst selects a(ny) cell within the PivotTable and then navigates to the &lt;i&gt;Options &lt;/i&gt;tab in the ribbon.&amp;nbsp; He or she then selects &lt;i&gt;Enable What-If Analysis &lt;/i&gt;located under the &lt;i&gt;What-If Analysis &lt;/i&gt;item on the far right of the tab.&amp;nbsp; This write-enables the PivotTable:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/3542.imag2.png"&gt;&lt;img style="margin-right: auto; margin-left: auto; display: block;" border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/3542.imag2.png" /&gt;&lt;/a&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/6747.image2.png"&gt;&lt;/a&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/3704.image2.png"&gt;&lt;/a&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/1854.image2.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With the PivotTable write-enabled, the analyst changes the score for Objective B.1 from 5 to 3. If he or she then selects &lt;i&gt;Calculate PivotTable with Changes&lt;/i&gt;, located under the &lt;i&gt;What-If Analysis &lt;/i&gt;item in the &lt;i&gt;Options&lt;/i&gt; tab of the ribbon, the average score for Objective B and the Grand Total are updated to reflect the data input:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/2262.image3.png"&gt;&lt;img style="margin-right: auto; margin-left: auto; display: block;" border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/2262.image3.png" width="511" height="281" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE &lt;/b&gt;If you would like the PivotTable to automatically recalculate itself with each data entry, select &lt;i&gt;Automatically Calculate Changes&lt;/i&gt; located under the &lt;i&gt;What-If Analysis&lt;/i&gt; item.&lt;/p&gt;
&lt;p&gt;Selecting Scenario 2 in the Slicer to the left of the PivotTable triggers another recalculation, this time using an uneven weighting to the objectives that&amp;rsquo;s appropriate to that particular scenario.&amp;nbsp; For example, in Scenario 2, Objective B.1 receives slightly less weight than Objectives B.2 and B.3 as reflected in the shift in the average score for Objective B between Scenarios 1 and 2:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/4111.image4.png"&gt;&lt;img style="margin-right: auto; margin-left: auto; display: block;" border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-46-24/4111.image4.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; The difference in weighting is so slight that the impact of this one change is lost in the rounding of the Grand Total value.&lt;/p&gt;
&lt;p&gt;Once the analyst has completed entering data and reviewing the results, he or she then chooses to either discard the changes to the cube, resetting it back to its original values, or publish the changes to the cube, altering the values presented to other analysts.&amp;nbsp; This is done by selecting either the &lt;i&gt;Discard Changes &lt;/i&gt;or &lt;i&gt;Publish Changes&lt;/i&gt; options (respectively) under the &lt;em&gt;W&lt;/em&gt;&lt;i&gt;hat-If Analysis&lt;/i&gt; item.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10314393" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Understanding What-If Analysis</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/understanding-what-if-analysis.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/understanding-what-if-analysis.aspx</id><published>2012-06-03T16:25:37Z</published><updated>2012-06-03T16:25:37Z</updated><content type="html">&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; This is the first of a series of entries on the topic of &lt;a title="Building Writeback Applications with Analysis Services" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx"&gt;Building Writeback Applications with Analysis Services&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Business analysts frequently encounter questions focused on the impact of potential change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What if we raised our parts and materials inventory?&amp;nbsp; How might that impact costs?&amp;nbsp; How might that impact the reliability of product delivery?&lt;/li&gt;
&lt;li&gt;What if we ran this promotion on this product?&amp;nbsp; How might that impact revenue and profits?&amp;nbsp; What impact might this have on inventories?&lt;/li&gt;
&lt;li&gt;What if we were required to reduce our budgets?&amp;nbsp; Where might we make those cuts and what activities might be impacted?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The what-if question is focused on uncertainty.&amp;nbsp; This differs significantly from the what-was question addressed (with relative certainty) using historical data sets.&amp;nbsp; To answer the what-was question, the analyst turns to the data warehouse.&amp;nbsp; To answer the what-if question, the analyst turns to a model.&lt;/p&gt;
&lt;p&gt;The model is a representation of the portion of the business the analyst needs to consider.&amp;nbsp; It accepts inputs and produces outputs based on these.&amp;nbsp; The analyst devises scenarios representing combinations of inputs to the model and studies the associated outputs.&amp;nbsp; This exercise clarifies the analyst&amp;rsquo;s understanding of the business and allows him or her to evaluate the range of outcomes likely to occur under differing scenarios.&amp;nbsp; Based on this, the analyst can then provide informed guidance on how best to deal with an uncertain situation.&lt;/p&gt;
&lt;p&gt;The model used depends on the problem to be solved.&amp;nbsp; A simple model might be nothing more than a diagram jotted down on a sheet of paper or a whiteboard which provides a heuristic for the analyst.&amp;nbsp; A more complex model might be assembled in a spreadsheet or developed using custom coding or statistical techniques.&amp;nbsp; Still other models might be assembled in a database using sets of related data and calculation logic for deriving values from these.&lt;/p&gt;
&lt;p&gt;This later kind of model fits neatly into the space occupied by OLAP technologies which is why most OLAP vendors provide writeback functionality with their products.&amp;nbsp; Writeback allows analysts to enter data (inputs) into a cube (model) which are then incorporated into the cube&amp;rsquo;s calculations (outputs).&amp;nbsp; Analysis Services, Microsoft&amp;rsquo;s OLAP technology, is no exception and has provided support for writeback since its first release (as OLAP Services) with SQL Server 7.0.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; Cell writeback, the form of writeback we will focus on first, is supported with all editions of Microsoft SQL Server Analysis Services.&amp;nbsp; Dimension writeback, a special case for writeback, is only supported with SQL Server Enterprise, Developer and Evaluation editions.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10314387" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Building a Writeback Application with Analysis Services</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-writeback-application-with-analysis-services.aspx</id><published>2012-06-03T16:21:00Z</published><updated>2012-06-03T16:21:00Z</updated><content type="html">&lt;p&gt;Recently, I delivered a presentation at the 2012 PASS SQL Rally titled Building a Writeback Application with Analysis Services.&amp;nbsp; Based on feedback from that session, I&amp;rsquo;ve decided to address this topic in my blog, making this information accessible to a wider audience and allowing me to address various points in a bit more depth than the 1-hour presentation format allows.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;There&amp;rsquo;s quite a bit of ground to cover here, so I won&amp;rsquo;t attempt to do this as a single blog post.&amp;nbsp; Instead, I&amp;rsquo;ll spread this over a series of entries, each covering a bite-sized chunk of the material.&amp;nbsp; I will address both cell writeback and dimension writeback, explain and demonstrate the interaction with Analysis Services, and provide code and database samples so you can try this at home.&amp;nbsp; As new entries to this series are added, I will update this page which will serve as a kind of table of contents to the series.&amp;nbsp; I hope this information is helpful and I look forward to your feedback.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/understanding-what-if-analysis.aspx"&gt;Understanding What-If Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-simple-demonstration-of-what-if-analysis.aspx"&gt;A Simple Demonstration of What-If Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/sidebar-the-other-what-if-analysis-options-in-excel.aspx"&gt;Sidebar: The Other What-If Analyses&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/a-technical-review-of-the-simple-demonstration.aspx"&gt;A Technical Review of the Simple Demonstration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/03/building-a-write-enabled-cube.aspx"&gt;Building a Write-Enabled Cube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/04/building-a-custom-writeback-application.aspx"&gt;Building a Custom Writeback Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/05/sidebar-the-ms-it-pattern-for-custom-writeback-applications.aspx"&gt;Sidebar: The MS IT Pattern for Custom Writeback Applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/16/understanding-allocations.aspx"&gt;Understanding Allocations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/19/allocation-across-a-parent-child-hierarchy.aspx"&gt;Sidebar: Allocation&amp;nbsp;across&amp;nbsp;a Parent-Child Hierachy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/06/20/introducing-dimension-writeback.aspx"&gt;Introducing Dimension Writeback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/19/writeback-to-a-parent-child-dimension.aspx"&gt;Writeback to a Parent-Child Dimension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/writeback-to-a-regular-dimension.aspx"&gt;Writeback to a Regular Dimension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/managing-writeback-cubes.aspx"&gt;Managing Writeback Cubes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2012/07/20/writeback-application-code-samples.aspx"&gt;Writeback Sample Downloads&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10314386" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author><category term="Writeback" scheme="http://blogs.msdn.com/b/data_otaku/archive/tags/Writeback/" /><category term="Analysis Services" scheme="http://blogs.msdn.com/b/data_otaku/archive/tags/Analysis+Services/" /></entry><entry><title>An Introduction to Big Data Concepts</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/11/01/an-introduction-to-big-data-concepts.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/11/01/an-introduction-to-big-data-concepts.aspx</id><published>2011-11-01T23:41:52Z</published><updated>2011-11-01T23:41:52Z</updated><content type="html">&lt;p&gt;The idea that data collected in computerized systems could be used to inform and thereby improve decision making has been around for quite some time.&amp;nbsp; Over the last couple decades, ideas of how to assemble a decision support system have coalesced around the concept of a data warehouse.&lt;/p&gt;
&lt;p&gt;The construction of a proper data warehouse requires a non-trivial investment. This investment is made with the expectation of benefits, but these are often difficult to enumerate prior to the warehouse&amp;rsquo;s construction and subsequent employment.&amp;nbsp; For this reason, the data warehouse requires a leap of faith.&lt;/p&gt;
&lt;p&gt;For many years, preparation for this leap was a significant part of the conversation with customers interested in Business Intelligence (BI). Today, in recognition of the data warehouse as a tool for navigating business challenges and uncertainty, the conversation tends to focus on maximizing the impact of BI on the organization.&lt;/p&gt;
&lt;p&gt;As customers focus on how best to extract insights from data, there is growing recognition of untapped data resources especially unstructured data. These data remain largely untapped because:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The value of these data relative to the cost of their processing and storage is low.&lt;/li&gt;
&lt;li&gt;These data are not easily stored and analyzed within the confines of the traditional data warehouse.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To illustrate these points, consider the data in a web log. These data could be very insightful to a business interested in engaging customers through a website. However, individual data records, holding information on a single page request or single image retrieval, are not likely to be high in value, especially over the longer periods of time in which data are stored in a traditional data warehouse.&lt;/p&gt;
&lt;p&gt;Furthermore, the structure of many elements within the log records, such as the URI of the referrer or the query string associated with a requested resource is highly variable in nature.&amp;nbsp; Differing questions posed against these data may require them to be interpreted in differing ways. Significant pre-processing of the data in order to neatly fit it into the traditional data warehouse may be unnecessary or even counter-productive.&lt;/p&gt;
&lt;p&gt;Web logs are a commonly cited form of unstructured data.&amp;nbsp; A better term for these data may be complex or mixed-typed data as at some level these data have a well understood and meaningful structure.&amp;nbsp; However, this structure is often as a level of granularity higher than the level at which analysis is to be performed, and it&amp;rsquo;s this mismatch that leads to the unstructured moniker. Other forms of unstructured data include XML or JSON documents, images, video, or PDF, Word, or HTML documents.&lt;/p&gt;
&lt;p&gt;The challenges of working with unstructured data, illustrated in the web log example, are often characterized in terms of &lt;i&gt;four Vs&lt;/i&gt;.&amp;nbsp;The &lt;i&gt;four Vs&lt;/i&gt; are identified as:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Volume &amp;ndash; Defined as the total number of bytes associated with the data. Unstructured data are estimated to account for 70-85% of the data in existence and the overall volume of data is rising.&lt;/li&gt;
&lt;li&gt;Velocity &amp;ndash; Defined as the pace at which the data are to be consumed.&amp;nbsp; As volumes rise, the value of individual data points tend to more rapidly diminish over time.&lt;/li&gt;
&lt;li&gt;Variety &amp;ndash; Defined as the complexity of the data in this class.&amp;nbsp; This complexity eschews traditional means of analysis.&lt;/li&gt;
&lt;li&gt;Variability &amp;ndash; Defined as the differing ways in which the data may be interpreted. Differing questions require differing interpretations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The four Vs articulate the broad challenges of working with unstructured data, but the dominant challenge tends to be in terms of data volume.&amp;nbsp; As a result, the effort to extract insights from unstructured data is often referred to as &lt;i&gt;Big Data&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Because of the challenges of the four Vs, Big Data necessitates an alternative approach to Business Intelligence.&amp;nbsp; This alternative approach, which we might refer to as the unstructured data warehouse or the Big Data warehouse, does not invalidate the traditional data warehouse but does acknowledge its limitations in extracting insights from the full range of available data resources.&amp;nbsp; What exactly is the unstructured data warehouse and how it will relate to the traditional (structured) data warehouse has yet to be determined, but ideas are beginning to coalesce around distributed, algorithmic technologies such as Apache Hadoop.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10232282" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>An Introduction to BigData Concepts: My Disclaimer</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/10/29/an-introduction-to-bigdata-concepts-my-disclaimer.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/10/29/an-introduction-to-bigdata-concepts-my-disclaimer.aspx</id><published>2011-10-29T15:02:56Z</published><updated>2011-10-29T15:02:56Z</updated><content type="html">&lt;p&gt;Recently, Microsoft announced its plans around Hadoop and all of a sudden BigData is part of the mainstream conversation we are having with our customers.&amp;nbsp; As a Business Intelligence practitioner, I couldn&amp;rsquo;t be more excited about this, but having been heavily steeped in the structured world of traditional Business Intelligence approaches, I have to admit wrapping my head around the concept of BigData and why it necessitates a new approach has been a bit challenging.&lt;/p&gt;
&lt;p&gt;I feel as though I am starting to grasp some parts of the BigData conversation and so I&amp;rsquo;m using this blog to share my understanding so that it may be challenged and that those similarly wrestling with this may hopefully find a nugget or two that helps them with their journey.&lt;/p&gt;
&lt;p&gt;To be clear, I am not a BigData expert, and though I work for Microsoft, I am not part of Microsoft&amp;rsquo;s BigData team.&amp;nbsp; Please interpret this and subsequent posts accordingly.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10231325" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Creating Your First FileTable in SQL Server Denali CTP3</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/09/20/creating-your-first-filetable-in-sql-server-denali-ctp3.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/09/20/creating-your-first-filetable-in-sql-server-denali-ctp3.aspx</id><published>2011-09-20T15:53:00Z</published><updated>2011-09-20T15:53:00Z</updated><content type="html">&lt;p&gt;With SQL Server Denali CTP3 &lt;a href="https://www.microsoft.com/betaexperience/pd/SQLDCTP3CTA/enus/" target="_blank"&gt;now available&lt;/a&gt;, I'm starting to explore some of the new Database Engine capabilities.&amp;nbsp; One that caught my attention is the &lt;a href="http://msdn.microsoft.com/en-us/library/ff929144(SQL.110).aspx" target="_blank"&gt;FileTable&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The FileTable builds upon FileStream storage which allows BLOB data to be stored as individual files separate from a database's data files.&amp;nbsp; In SQL Server 2008 (and 2008 R2), interactions with the FileStream files took place either through T-SQL or through code which engaged with OpenSqlFileStream API.&amp;nbsp; This was an interesting direction for applications with large volumes of BLOB data which needed to be accessed quickly, but it wasn't the most accessible implementation. (For more info on FileStream storage including its benefits and trade-offs, check out &lt;a href="http://msdn.microsoft.com/en-us/library/cc949109(SQL.100).aspx" target="_blank"&gt;this excellent white paper&lt;/a&gt;&amp;nbsp;which includes best practices for FileStream configuraiton which you will want to employ.)&lt;/p&gt;
&lt;p&gt;The FileTable addresses this by making the Windows share associated with the externally stored files directly engageable and by allowing the share to employ a familiar, hiearchical folder structure. (The folder structure is represented by the underutilized &lt;a href="http://msdn.microsoft.com/en-us/library/bb677173(v=SQL.100).aspx"&gt;hierarchyid data type &lt;/a&gt;first introdued in SQL Server 2008.&amp;nbsp; If you aren't familiar with it, &lt;a href="http://msdn.microsoft.com/en-us/library/bb677213(v=SQL.100).aspx" target="_blank"&gt;check it out&lt;/a&gt;.) This, along with the &lt;a href="http://msdn.microsoft.com/en-us/library/gg492075(SQL.110).aspx"&gt;semantic&amp;nbsp;search &lt;/a&gt;capabilities of Denali, will be what make FileStream take off for database developers.&lt;/p&gt;
&lt;p&gt;However, there are quite a number of steps involved with configuring a SQL Server instance and database before you can create your first FileTable, and if you are not familiar with the setup of FileStream storage, these steps can be challenging to perform. Having stumbled a couple times myself before finally getting it right, I figured document the steps involved with enabling the environment and creating a simple FileTable in SQL Server Denali CTP3.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;1. Enable the FileStream driver on the SQL Server instance.&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;a. Open SQL Server Configuration Manager.&lt;br /&gt; b. Navigate to the SQL Server Services folder in the left-hand pane.&lt;br /&gt; c. In the right-hand pane, right-click the Database Engine instance on which you want to enable FileStream support and select Properties.&lt;br /&gt; d. In the Properties dialog, navigate to the FILESTREAM tab.&lt;br /&gt; e. Check the Enable FILESTREAM for Transact-SQL access and Enable FILESTREAM for file I/O access options.&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; You can also change the name of the Windows share, but for the purpose of these instructions, I'll leave it as its default,&amp;nbsp;&lt;em&gt;i.e&lt;/em&gt;. the name of the instance.&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;f. Check the Allow remote client access option for the purposes of this post. For production deployments, this may or may not be the right option for you and requires&amp;nbsp;a consideration of the accessibility and security trade-offs.&lt;br /&gt; i. Click the Apply button and then close the Properties dialog and SQL Server Configuration Manager.&lt;/p&gt;
&lt;p&gt;At this point, you can see that the server now exposes a Windows share using the name of the Database Engine instance.&amp;nbsp;You can see this by opening Windows Explorer and navigating to &lt;a href="file://\\127.0.0.1"&gt;\\127.0.0.1&lt;/a&gt;.&amp;nbsp; If you enabled remote access on the FileStream share (in Step 1f), you can access the share but it will be empty at this point. (In SQL Server 2008 and 2008 R2, attempting to access the share in this manner would result in an error regardless of the remote access setting.)&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;2. Enable SQL Server to use the FileStream driver.&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;a. Open SQL Server Management Studio and cancel the&amp;nbsp;Connect to Server&amp;nbsp;dialog.&lt;br /&gt; b. Click the New Query button and connect to the SQL Server Database Engine instance you configured in Step 1.&lt;br /&gt; c. In the query window, execute the following statements:&lt;/p&gt;
&lt;p style="padding-left: 90px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;exec sp_configure filestream_access_level, 2;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; reconfigure;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; The filestream_access_level configuration setting set in Step 2d takes one of three values: 0, 1, or 2.&amp;nbsp; The default value, 0, disables FileStream support.&amp;nbsp; The value 1 enables T-SQL only access to FileStream files, and the value 2 enables both T-SQL and Win32 (direct) access to the files.&lt;/p&gt;
&lt;p&gt;With FileStream now configured at the instance-level, you can now setup a new (example) database employing FileStream storage.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;3. Create a new database employing a FileStream file group.&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;a. In the query window used in Step 2d (or a new one), execute the following statement to create a new database:&lt;/p&gt;
&lt;p style="padding-left: 90px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;create database FileTableDemo;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;b. In that same query window, execute the following statement to add a FileStream file group to the database:&lt;/p&gt;
&lt;p style="padding-left: 90px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;alter database FileTableDemo &lt;br /&gt;add filegroup FileStreamGroup1 contains filestream;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;c. In that same query window, execute the following statement to define the storage associated with the FileStream file group added in the previous step:&lt;/p&gt;
&lt;p style="padding-left: 90px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;alter database FileTableDemo&lt;br /&gt;add file (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: courier new,courier;"&gt;name = FileStream1, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; filename = 'D:\Temp\FileStreamFileGroup1' &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) to filegroup FileStreamGroup1;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; Steps 3a, b, and c could be combined into a step using a single CREATE DATABASE statement.&amp;nbsp; It's been decomposed into smaller steps here for greater transparency.&lt;/p&gt;
&lt;p&gt;This last step deserves a bit more discussion. The path to the FileStream storage, as identified in the filename setting, must be a valid path on the SQL Server system up to the last folder in the path.&amp;nbsp; In other words, D:\Temp must exist for the previous statement to work.&amp;nbsp; However, the last folder, FileStreamFileGroup1 in the case of the previous statement, must not exist.&amp;nbsp; That folder will be created by SQL Server upon statement execution.&lt;/p&gt;
&lt;p&gt;With the database in place, you now need to configure how the database will present and control interactions&amp;nbsp;with the&amp;nbsp;FileStream data.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;4. Configure how the database handles access to the FileStream data.&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;a. In the query windows from previous steps, define the name of the Share subfolder through which FileStream files associated with this database will be shared:&lt;/p&gt;
&lt;p style="padding-left: 90px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;alter database FileTableDemo set filestream ( directory_name = 'FileTableDemo' );&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;b. In the query window, execute the following statement to enable direct read and write access to the FileStream data:&lt;/p&gt;
&lt;p style="padding-left: 90px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;alter database FileTableDemo set filestream( non_transacted_access = full );&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; Options for non_transacted_access are off, read_only, and full.&amp;nbsp; Off disables non-transactional access so that data in the FileTableDemo subfolder will not be accessible.&amp;nbsp; Read_only provides read-only access to files (outside a transaction as handled through the OpenSqlFileStream API). Full allows files to be read and written through the subfolder.&lt;/p&gt;
&lt;p&gt;If you accessed the share earlier, you might wish to review it again now.&amp;nbsp; The instance's share at &lt;a href="file://\\127.0.0.1" target="_blank"&gt;\\127.0.0.1&lt;/a&gt; now has a FileTableDemo subfolder per&amp;nbsp;Step 4a.&lt;/p&gt;
&lt;p&gt;With all this in place, you can now define a filetable in the database.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;5. Create a FileTable within the FileTableDemo database by executing the following statement in the query window from the previous step:&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;use FileTableDemo;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; go&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt; create table MyFileTable as filetable;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 60px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; The CREATE TABLE statement used in the last step is very simplistic compared to what is possible with the structure of a FileTable but it provides a good starting point for working with this new feature.&amp;nbsp; For more info on the broader syntax on the CREATE TABLE ... AS FILETABLE statement, please see &lt;a href="http://msdn.microsoft.com/en-us/library/gg509088(v=SQL.110).aspx#HowToCreate" target="_blank"&gt;this document&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With a FileTable now defined within the FileTableDemo database, you can now reconnect to &lt;a href="file://\\127.0.0.1"&gt;\\127.0.0.1&lt;/a&gt; and access the instance share.&amp;nbsp; The FileTableDemo subfolder defined in Step 4a now has its own subfolder, MyFileTable, &amp;nbsp;named for the FileTable created in Step 5.&amp;nbsp; As the database has been configured to allow full non-transactional access to this folder, you can drag and drop files within the FileTable folder and even create subfolders under it.&amp;nbsp; All of these will be reflected in the MyFileTable table when you interact with it using T-SQL.&amp;nbsp; As you use T-SQL to insert, update, and delete data in the FileTable table, those changes will be reflected in the associated folder on the Windows share.&amp;nbsp; Pretty cool stuff!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10214132" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Virtualizing the SharePoint 2010 Database-Tier</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/07/11/virtualizing-the-sharepoint-2010-database-tier.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/07/11/virtualizing-the-sharepoint-2010-database-tier.aspx</id><published>2011-07-11T18:09:30Z</published><updated>2011-07-11T18:09:30Z</updated><content type="html">&lt;p&gt;Over the last few months, I&amp;rsquo;ve had a number of conversations with customers regarding the virtualization of SQL Server for the database-tier of SharePoint Server 2010 deployments.&amp;nbsp; Historically, administrators have been hesitant to virtualize SQL Server database servers out of concerns for performance. With advances in virtualization technology and the adoption of new IT standards, virtual deployments have become the new norm in many organizations.&lt;/p&gt;
&lt;p&gt;Still, virtualization is not the right choice for every workload. The purpose of this blog is to highlight the key considerations that go into deciding whether to virtualize the SharePoint database-tier.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Support for Virtualization&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The first thing to consider is the &lt;a href="http://support.microsoft.com/kb/956893"&gt;SQL Server support policy for virtualization&lt;/a&gt;. &amp;nbsp;SQL Server 2005+ enjoys support on a wide range of virtualization platforms with two important limitations.&amp;nbsp; First, mobility technologies, &lt;i&gt;i.e.&lt;/i&gt; VMWare VMotion, are not supported with the exception of Hyper-V Live Migration which has received thorough testing with SQL Server.&amp;nbsp; Second, virtualization snapshots are not supported on any platform, including Hyper-V.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Disk I/O Requirements of the Database-Tier&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The next thing to consider is the disk I/O workload generated by SharePoint on the database-tier.&amp;nbsp; Formal testing is required to determine the requirements of a specific deployment, but &lt;a href="http://www.msteched.com/2010/Europe/OFS320"&gt;Microsoft IT&amp;rsquo;s standard&lt;/a&gt; of 1,000 IOPS per TB of data or 5,000 site collections is a good starting point for more highly-utilized deployments.&amp;nbsp; On top of this, MS IT reserves another 150-200% of capacity for periods of high utilization and burst events such as database backups.&lt;/p&gt;
&lt;p&gt;With disk I/O requirements known, the next thing to consider is how those requirements will be met.&amp;nbsp; With any server, there is interplay between CPU, memory, controllers, and the disk subsystem which must be understood to achieve optimal throughput.&amp;nbsp; &lt;a href="http://technet.microsoft.com/en-us/library/cc966412.aspx"&gt;This white paper&lt;/a&gt; provides some insight into this and shows how disk I/O capacity can be determined for a server.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; The configuration of the virtual machine can have a significant impact on SQL Server throughput.&amp;nbsp; Consider &lt;a href="http://download.microsoft.com/download/d/9/4/d948f981-926e-40fa-a026-5bfcf076d9b9/SQL2008inHyperV2008.docx"&gt;this guidance&lt;/a&gt; on the deployment of SQL Server on Hyper-V technology.&lt;/p&gt;
&lt;p&gt;It is possible single machine will not be capable of achieving the IOPS required to support a SharePoint workload.&amp;nbsp; This is true of both physical and virtual machines but more likely with virtual machines given their more limited scale.&amp;nbsp; If the IOPS requirements exceed what can be supported by a single machine, consider scaling up (if possible) or &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=6096"&gt;scaling out&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Resource Isolation and Predictable Capacity&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Finally, keep in mind any shared resources associated a server.&amp;nbsp; If these resources are not isolated, the available capacity of the server at any point in time will be dependent on the consumption of these resources by other associated servers.&amp;nbsp; With virtual machines, shared resources can include CPUs, memory (when dynamic), network cards, controllers and disk subsystems.&amp;nbsp; With physical machines, shared resources are typically limited to disk subsystems.&amp;nbsp; With both virtual and physical machines, shared resources can be configured for isolation and, therefore, predictable capacity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When designing the database-tier, consider first and foremost the&amp;nbsp;infrastructure's ability&amp;nbsp;to&amp;nbsp;accomodate the SharePoint-generated workload. Virtualization adds many more factors to the consideration but success on a virtualized platform is achievable.&amp;nbsp; Likewise, a physical deployment does not guarantee success if not built against known requirements.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10185265" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Securing the Data Warehouse</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/28/securing-the-data-warehouse.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/06/28/securing-the-data-warehouse.aspx</id><published>2011-06-28T13:21:16Z</published><updated>2011-06-28T13:21:16Z</updated><content type="html">&lt;p&gt;After completing a series of posts on &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/21/build-secure-database-applications-with-microsoft-sql-server.aspx"&gt;Building Secure Database Applications&lt;/a&gt;, the question of how the practices and features highlighted apply to data warehouses arose.&lt;/p&gt;
&lt;p&gt;In a traditional database application, the database is a behind-the-scenes element, accessed indirectly by the user through an application front-end or middle-tier. In such an architecture, interaction with the database can be very tightly controlled to ensure security.&lt;/p&gt;
&lt;p&gt;In a data warehouse, the database is the application.&amp;nbsp; Users interact more directly with the tables and views it houses through numerous applications, issuing a wide variety of queries which may or may not be known in advance.&amp;nbsp; The techniques that would be applied to secure the database behind a traditional application could severely constrain the users of the data warehouse and undermine its success.&lt;/p&gt;
&lt;p&gt;Still, security is essential. Without appropriate security, the data warehouse, as the centralized hub of information on the status of the business, becomes just as much a liability as it is an asset. How then should it be secured?&lt;/p&gt;
&lt;p&gt;In the previous series of posts, seven high-level considerations were put forward for securing a database application.&amp;nbsp; Revisiting these considerations in the context of a data warehouse provides some changes in guidance:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; If you haven&amp;rsquo;t read the original posts associated with each bulletpoint below, please click on the provided link to provide background on the additional commentary.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/21/harden-the-database-server.aspx"&gt;Harden the Server&lt;/a&gt;&lt;/b&gt; - No changes here.&amp;nbsp;The software, operating system, network, and physical environment supporting SQL Server requires the same protection as before.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/27/regulate-network-connectivity.aspx"&gt;Regulate Network Connectivity&lt;/a&gt;&lt;/b&gt; &amp;ndash; The guidance provided here is intended to make SQL Server harder to locate on the network by all but the intended applications.&amp;nbsp; As the data warehouse is expected to provide flexible access to a variety of applications, hiding the SQL Server instance, disabling the SQL Browser, and employing application-specific endpoints doesn't exactly support this objective.&amp;nbsp; Configuring non-standard TCP ports and named pipes some albeit little additional security to the data warehouse.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/22/secure-the-authentication-process.aspx"&gt;Secure the Authentication Process&lt;/a&gt; &lt;/b&gt;&amp;ndash; The exclusive use of Windows authentication is strongly encouraged so that you may more accurately monitor end-user activity.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/23/assign-minimal-permissions.aspx"&gt;Assign Minimal Permissions&lt;/a&gt; &lt;/b&gt;&amp;ndash; Users of the data warehouse typically require read only permission to the tables and views in their domain. By carving the database up into separate schemas (with differing owners to break ownership chains), custom database roles can be built with appropriate access to individual schemas. Synonyms and views can be employed to make database objects, e.g. conformed dimension tables, accessible across multiple domains.&amp;nbsp; Another approach to assigning minimal permissions is to introduce an intermediate application between the user and the data warehouse. Such an application should support a fine-grain security model and query the data warehouse on behalf of the user.&amp;nbsp; Examples of such applications include SQL Server Analysis Services and the soon to be release Business Intelligence Semantic Model (BISM).&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="padding-left: 60px;"&gt;&lt;b&gt;NOTE &lt;/b&gt;Column-level security is often suggested in data warehousing scenarios.&amp;nbsp; Please be aware that the has_perms_by_name() function, which is called directly and indirectly by many applications to determine which objects are available to a user, will only identify a table as accessible if all fields in the table are accessible to the user.&amp;nbsp; As a result, tables on which column-level restrictions have been defined may not appear to the user in their application.&amp;nbsp; Please test the impact of column-level security on the specific applications in your portfolio before employing this feature.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/25/encrypt-the-data.aspx"&gt;Encrypt the Data&lt;/a&gt;&lt;/b&gt; &amp;ndash; Transparent Data Encryption (TDE) is a must if the data warehouse contains any data of significance.&amp;nbsp;This will prevent someone from walking off with a backup of the database which could then be used to learn the ins-and-outs of your business. IPSec and SSL to encrypt over the wire should also be considered even if the database is used exclusively over a secured, internal network.&amp;nbsp; Encryption over the wire prevents malicious users from intercepting data they might not otherwise have access to and/or by-passing the SQL audit.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/26/defend-against-sql-injection.aspx"&gt;Defend against SQL Injection&lt;/a&gt;&lt;/b&gt; &amp;ndash; If formal applications are built on the data warehouse, the standard guidance on defending against SQL injection applies.&amp;nbsp; However, the kinds of the tools users typically use to interact with the data warehouse aren't usually very susceptible to this kind of attack. Still, using the SQL audit feature to keep track of who is using which tools and then following up with a brief investigation of those tools is a good idea.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/27/monitor-amp-enforce-security-policies.aspx"&gt;Monitor &amp;amp; Enforce Security Policies&lt;/a&gt; &lt;/b&gt;&amp;ndash; The guidance here is relatively unchanged though you may wish to apply the SQL audit a bit more liberally where there is sensitive data.&amp;nbsp; As mentioned in the related post, there is overhead associated with the audit but the frequency of queries within the data warehouse is often less than an active OLTP application so that the cumulative overhead of the audit should be lower.&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10180912" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Regulate Network Connectivity</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/27/regulate-network-connectivity.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/06/27/regulate-network-connectivity.aspx</id><published>2011-06-27T19:20:00Z</published><updated>2011-06-27T19:20:00Z</updated><content type="html">&lt;p&gt;SQL Server accepts client connections over specific network protocols and (for lack of a better term) associated channels. The combination of network protocol, a channel, and the type of communication taking place over it is managed from within SQL Server as an endpoint.&lt;/p&gt;
&lt;p&gt;SQL Server comes pre-configured with 5 endpoints intended to support traditional client-server communications.&amp;nbsp; These are identified in this table:&lt;/p&gt;
&lt;table style="width: 674px;" border="0" cellspacing="0" cellpadding="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="143"&gt;
&lt;p&gt;&lt;strong&gt;Endpoint&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="126"&gt;
&lt;p&gt;&lt;strong&gt;Network&amp;nbsp;&lt;/strong&gt;&lt;strong&gt;Protocol&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="404"&gt;
&lt;p&gt;&lt;strong&gt;Channel&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="143"&gt;
&lt;p&gt;Dedicated&amp;nbsp;Admin Connection&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="126"&gt;
&lt;p&gt;TCP&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="404"&gt;
&lt;p&gt;This endpoint is associated with a TCP port.&amp;nbsp;&amp;nbsp; With default instances of SQL Server, this is typically TCP port 1434. With named instances of SQL Server, this is typically a TCP port dynamically&amp;nbsp;assigned during the start-up of the SQL Server service. With both named and&amp;nbsp;default instances, the TCP port can be set to a differing (and fixed) value&amp;nbsp;through the SQL Server Configuration Manager.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="143"&gt;
&lt;p&gt;TSQL Local&amp;nbsp;Machine&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="126"&gt;
&lt;p&gt;Shared&amp;nbsp;Memory&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="404"&gt;
&lt;p&gt;This endpoint is not associated with a channel&amp;nbsp;as the protocol directly transfers data between client and server through&amp;nbsp;memory.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="143"&gt;
&lt;p&gt;TSQL Named&amp;nbsp;Pipes&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="126"&gt;
&lt;p&gt;Named&amp;nbsp;Pipes&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="404"&gt;
&lt;p&gt;This endpoint is associated with a named pipe. With default instances of SQL Server, the server identifies this named pipe&amp;nbsp;as \\.\pipe\sql\query and clients identify this named pipe as \\&lt;i&gt;&amp;lt;computername&amp;gt;&lt;/i&gt;\pipe\sql\query. With named instances of SQL Server, the server identifies this named pipe as \\.\pipe\MSSQL$&lt;i&gt;&amp;lt;instance name&amp;gt;&lt;/i&gt;\sql\query and&amp;nbsp;clients identify this named pipe as \\&lt;i&gt;&amp;lt;computername&amp;gt;&lt;/i&gt;\pipe\MSSQL$&lt;i&gt;&amp;lt;instancename&amp;gt;&lt;/i&gt;\sql\query. The name of the pipe can be changed using the SQL&amp;nbsp;Server&amp;nbsp;Configuration Manager.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="143"&gt;
&lt;p&gt;TSQL Default TCP&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="126"&gt;
&lt;p&gt;TCP&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="404"&gt;
&lt;p&gt;This endpoint is associated with a TCP port.&amp;nbsp;With default instances of SQL Server, this is typically TCP port 1433. With&amp;nbsp;named instances of SQL Server, this is typically a TCP port dynamically&amp;nbsp;&amp;nbsp; assigned during the start-up of the SQL Server service. With both named and&amp;nbsp;default instances, the TCP port can be set to a differing (and fixed) value&amp;nbsp;through the SQL Server Configuration Manager.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="143"&gt;
&lt;p&gt;TSQL&amp;nbsp;Default VIA&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="126"&gt;
&lt;p&gt;VIA&lt;/p&gt;
&lt;/td&gt;
&lt;td valign="top" width="404"&gt;
&lt;p&gt;This endpoint is associated with VIA port&amp;nbsp;0:1433 on both default and named instances of SQL Server.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As the Shared Memory protocol can only be used locally on the server, the Dedicated Admin Connection (DAC) is configured (by default) for local connections only, and VIA is a deprecated protocol, the endpoints associated with these will not be discussed further in this post. That leaves the TSQL Named Pipes and TSQL Default TCP endpoints.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE &lt;/b&gt;In the context of this discussion, TCP and Named Pipes refer to protocols employed by SQL Server.&amp;nbsp; The use of one protocol or the other affects how SQL Server (and the client) manage and interact buffers through which data is exchanged. These protocols are employed a higher level in the networking stack than protocol employed by the operating system, typically TCP/IP. To illustrate this, consider that communications via the (SQL Server) Named Pipes protocol are handled over TCP port 445.&lt;/p&gt;
&lt;p&gt;Returning to the concept of a client connecting to a SQL Server instance, the client must know a combination of network protocol and channel over which SQL Server is accepting connection requests. The client may &amp;ldquo;guess&amp;rdquo; these using well-known combinations, such as a default instance of SQL Server using the TCP protocol to take connections via TCP port 1433.&amp;nbsp; However, if well-known combinations are not being used by the instance, the client must either be provided the network protocol and channel information in advance or a secondary service, the SQL Server Browser Windows service, must be available to provide this information on request.&lt;/p&gt;
&lt;p&gt;The SQL Server Browser Windows service (SQL Browser) listens on UDP port 1434 for request for information. It responds to requesters with the network protocol and channel information (as well as other metadata) for all SQL Server (Database Engine) instances on the server.&amp;nbsp; A client can then use this information to attempt a connection to a SQL Server instance.&lt;/p&gt;
&lt;p&gt;To secure network connectivity to SQL Server consider moving instances from well-known network protocol and channel combinations.&amp;nbsp; Consider too disabling the SQL Server Browser Windows service or simply registering a sensitive instance of SQL Server as hidden so that SQL Browser does not return any information on it to requestors.&amp;nbsp; Information on changing TCP ports and pipe names is found &lt;a href="http://msdn.microsoft.com/en-us/library/ms177440.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/ms189321.aspx"&gt;here&lt;/a&gt;, respectively.&amp;nbsp; Information on hiding a SQL Server instance is found &lt;a href="http://msdn.microsoft.com/en-us/library/ms179327.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To take this one step further, consider establishing application-specific TCP endpoints, each associated with a differing TCP port.&amp;nbsp; Doing so provides you the ability to carefully administer how differing applications connect to an instance of SQL Server. Should there be a need to disable connectivity for one application, its endpoint can be stopped while other endpoints remain active for another applications. Information on configuring multiple TCP ports for a SQL Server instance is found &lt;a href="http://technet.microsoft.com/en-us/library/ms189310.aspx"&gt;here&lt;/a&gt;.&amp;nbsp; Information on granting and revoking endpoint permissions are found &lt;a href="http://msdn.microsoft.com/en-us/library/ms187811.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/ms186798.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; Only the TCP and VIA network protocols support the creation of multiple endpoints.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;DEMONSTRATION&lt;/b&gt; To review the steps required to configure an application-specific TCP endpoint, please review &lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/23/end-point-demo.aspx"&gt;this post&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10179589" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>Monitor &amp; Enforce Security Policies</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/27/monitor-amp-enforce-security-policies.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/06/27/monitor-amp-enforce-security-policies.aspx</id><published>2011-06-27T18:20:00Z</published><updated>2011-06-27T18:20:00Z</updated><content type="html">&lt;p&gt;Once a security policy is defined, it then needs to be monitored and enforced to ensure compliance.&amp;nbsp; SQL Server provides two features for this: policy-based management and audit.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Policy-Based Management&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Introduced with SQL Server 2008, policy-based management (PBM) allows administrators to define conditions for various facets of the database environment.&amp;nbsp; These conditions, combined to form policies, are then evaluated against policy targets on-demand, on-schedule, or automatically as changes take place. For more information on PBM, check out &lt;a href="http://msdn.microsoft.com/en-us/library/bb510667.aspx"&gt;this document&lt;/a&gt; in Books Online.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; Many of the facets of interest from a security perspective only support on-demand or on-schedule evaluation. To automate evaluation, consider using the on-schedule option and defining alerts as described in the &lt;i&gt;Configuring Alerts to Notify Policy Administrators of Policy Failures&lt;/i&gt; section of the previously referenced document.&lt;/p&gt;
&lt;p&gt;SQL Server allows you to define custom policies but also provides access to a number of policies based on established best practices, many of which are security related. Information on importing and employing these best practice policies can be found in &lt;a href="http://msdn.microsoft.com/en-us/library/ee342165.aspx"&gt;this tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE &lt;/b&gt;Many of these best practices are also evaluated through the the &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=15289"&gt;SQL Server Best Practices Analyzer&lt;/a&gt; and &lt;a href="https://www.systemcenteradvisor.com/"&gt;System Center Advisor&lt;/a&gt;.&amp;nbsp; If these tools are not part of your administrative toolkit, it&amp;rsquo;s is well worth exploring them through the provided links.&lt;/p&gt;
&lt;p&gt;Finally, PBM, as implemented in SQL Server 2008 and 2008 R2, provides some multi-server capabilities. Still, the Enterprise Policy Management Framework, &lt;a href="http://www.codeplex.com/EPMFramework"&gt;available on Codeplex&lt;/a&gt; and documented in &lt;a href="http://msdn.microsoft.com/en-us/library/dd542632.aspx"&gt;this white paper&lt;/a&gt;, extends PBM, making it a more effective tool for administrators of larger environments.&amp;nbsp; The Framework has the added advantage of bringing PBM capabilities to SQL Server 2005 and 2000 deployments.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Audit&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;SQL Server audit allows information related to various events occurring within a database or SQL Server instance to be recorded for later review. Audit works through the definition of an audit (log) to which data is recorded and the identification of events to record to that log through audit specifications.&amp;nbsp; For a more in-depth review of SQL Server audit, please review &lt;a href="http://msdn.microsoft.com/en-us/library/dd392015(v=SQL.100).aspx"&gt;this document&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;SQL Server audit supports three different audit logs: a binary file, the Windows Application log, and the Windows Security log.&amp;nbsp; The Windows Security log is the most secure of these three options as special permissions are required to write to this log.&amp;nbsp; These permissions also make configuration of the Windows Security log as the audit destination a bit more challenging.&amp;nbsp; To read more about configuring the Windows Security log to accept audit records, please review &lt;a href="http://msdn.microsoft.com/en-us/library/cc645889.aspx"&gt;this document&lt;/a&gt;.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;b&gt;NOTE&lt;/b&gt; If the Windows Security or Application log is used as the audit log, tools such as System Center Operations Manager can be used to consolidate audit information from across multiple servers.&lt;/p&gt;
&lt;p&gt;When configuring audit specifications, keep in mind that recording event data to the logs adds overhead to the audited actions.&amp;nbsp; While event data can be queued in memory before being written to the audit log, the best option for minimizing the performance overhead is to simply be selective of the events being audited. With some event types, those events recorded to the audit log can be restricted to those associated with a specific database object and/or user or role.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10179553" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>SQL Injection Demo</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/26/sql-injection-demo.aspx" /><id>http://blogs.msdn.com/b/data_otaku/archive/2011/06/26/sql-injection-demo.aspx</id><published>2011-06-26T13:21:00Z</published><updated>2011-06-26T13:21:00Z</updated><content type="html">&lt;p&gt;The purpose of this post is to demonstrate a simple SQL injection attack.&amp;nbsp; For information on securing a database against SQL injection, please review this&amp;nbsp;&lt;a href="http://blogs.msdn.com/b/data_otaku/archive/2011/06/26/defend-against-sql-injection.aspx"&gt;post&lt;/a&gt;.&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt; Implementing an actual SQL injection attack against a system for which you have not been provided explicit&amp;nbsp;authorization may result in your prosecution. This post is intended to educate folks on the basic pattern so that they may plan their defense.&amp;nbsp; The pattern/technique demonstrated here is highly simplistic and widely demonstrated and discussed&amp;nbsp;in&amp;nbsp;forums related to SQL injection defense.&lt;/p&gt;
&lt;p&gt;The first step is to set up a demonstration database.&amp;nbsp; In this database, a few tables and a stored procedure using dynamic SQL will later be created:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;USE master;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;IF EXISTS (SELECT * FROM sys.databases WHERE name = 'SqlInjectionDemo') DROP DATABASE SqlInjectionDemo;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;CREATE DATABASE SqlInjectionDemo;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Next, a couple tables representing products in an online product catalog will be setup and populated:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;USE SqlInjectionDemo;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;CREATE TABLE dbo.ProductCategory (ProductCategoryID int not null, Name nvarchar(50));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;INSERT INTO dbo.ProductCategory VALUES (1, 'Electronics'), (2, 'Media');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;CREATE TABLE dbo.Product (ProductID int not null, ProductCategoryID int not null);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;INSERT INTO dbo.Product VALUES (1,1), (2,1), (3,1), (4, 2), (5, 2), (6, 2);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To access the&amp;nbsp;products in the product catalog, a stored procedure will be employed which accepts as its parameter the name of the product category on which to restrict the products returned:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;CREATE PROC dbo.spGetProducts @ProductCategoryName NVARCHAR(50)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; DECLARE @sql NVARCHAR(MAX)='';&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; SET @sql =&amp;nbsp; 'SELECT a.* '+&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'FROM dbo.Product a '+&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'INNER JOIN dbo.ProductCategory b '+&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'ON a.ProductCategoryID=b.ProductCategoryID '+&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'WHERE b.NAME='''+ @ProductCategoryName +''''&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; EXEC(@sql)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The application is intended to call this stored procedure passing the name of a product category.&amp;nbsp; When this takes place, the proc returns a limited set of data:&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;EXEC spGetProducts N'Electronics'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;ProductID&amp;nbsp;&amp;nbsp; ProductCategoryID&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;----------- -----------------&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;(3 row(s) affected)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;However, using SQL injection techniques, a malicious user could alter the statement logic to return all products:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;EXEC spGetProducts N''' OR ''1''=''1'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;ProductID&amp;nbsp;&amp;nbsp; ProductCategoryID&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;----------- -----------------&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;(6 row(s) affected)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Going one step further, a malicious user could terminate the original SQL statement and append another one disclosing still more information:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;EXEC spGetProducts N''';SELECT * FROM sysobjects WHERE NAME &amp;lt;&amp;gt; '''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;ProductID&amp;nbsp;&amp;nbsp; ProductCategoryID&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;----------- -----------------&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;(0 row(s) affected)&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;--------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;sysrscols&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;sysrowsets&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;sysallocunits&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #333399; font-family: courier new,courier;"&gt;(56 row(s) affected)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To defend against this attack, the stored procedure simply needs to be rewritten as follows:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;ALTER PROC dbo.spGetProducts @ProductCategoryName NVARCHAR(50)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; SELECT a.*&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; FROM dbo.Product a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; INNER JOIN dbo.ProductCategory b&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON a.ProductCategoryID=b.ProductCategoryID&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; WHERE b.NAME = @ProductCategoryName&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To be fair to developers, not all dynamic SQL is as easily replaced with parameterized SQL.&amp;nbsp; Still, avoiding dynamic SQL is the key to preventing SQL injection.&lt;/p&gt;
&lt;p&gt;To clean up the demo environment, execute the following statements:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;USE master;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span style="font-family: courier new,courier;"&gt;DROP DATABASE SqlInjectionDemo;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier;"&gt;GO&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10179154" width="1" height="1"&gt;</content><author><name>Bryan C Smith</name><uri>http://blogs.msdn.com/bryan.c.smith_4000_live.com/ProfileUrlRedirect.ashx</uri></author></entry></feed>