<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Danny Quinn</title>
	<atom:link href="http://dannyquinn.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://dannyquinn.co.uk</link>
	<description>.NET &#38; SQL Server</description>
	<lastBuildDate>Wed, 22 Feb 2012 21:42:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>ReportViewer Control and ASP.NET</title>
		<link>http://dannyquinn.co.uk/2012/02/22/reportviewer-control-and-asp-net/</link>
		<comments>http://dannyquinn.co.uk/2012/02/22/reportviewer-control-and-asp-net/#comments</comments>
		<pubDate>Wed, 22 Feb 2012 21:42:49 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[SSRS]]></category>
		<category><![CDATA[Server Controls]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=873</guid>
		<description><![CDATA[I read somewhere that you could embed SSRS in a .NET web page and the other day I thought this would be a good way to add few gauges. To start with, I created a new Report Server Project using Visual Studio 2008 BIDS.&#160;&#160;After adding a data source and a simple dataset, I dragged three [...]]]></description>
			<content:encoded><![CDATA[<p>I read somewhere that you could embed <b>SSRS</b> in a .NET web page and the other day I thought this would be a good way to add few gauges.</p>
<p>To start with, I created a new <b>Report Server Project</b> using <b>Visual Studio 2008 BIDS</b>.&nbsp;&nbsp;After adding a data source and a simple dataset, I dragged three gauges from the toolbox onto the design area.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer1.png" alt="" title="ReportViewer1" width="454" height="249" class="aligncenter size-full wp-image-876" /></p>
<p>After deploying the report to my local copy of IIS, I browsed the report server to test the report functioned correctly.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer2.png" alt="" title="ReportViewer2" width="430" height="209" class="aligncenter size-full wp-image-877" /></p>
<p>Next I opened a .NET web application using <b>Visual Studio 2010</b>, right clicked on the project (in the solution explorer) and selected <b>Add Reference</b>.&nbsp;&nbsp;From the list I selected <b>Microsoft.ReportViewer.WebForms Version 10</b>.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer3.png" alt="" title="ReportViewer3" width="473" height="220" class="aligncenter size-full wp-image-878" /></p>
<p>I added a new web page and then selected the <b>ReportViewer</b> control from the toolbox and dragged it onto the web page.&nbsp;&nbsp;I also had to add a <b>ScriptManager</b> control to the page.</p>
<pre class="brush:xml;highlight:[3,4,16,18];">&lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test_Report.aspx" Inherits="Test_Report" %&gt;

&lt;%@ Register Assembly="Microsoft.ReportViewer.WebForms"
        Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb"%&gt;

&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head runat="server"&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id="form1" runat="server"&gt;
    &lt;div&gt;
        &lt;asp:ScriptManager runat="server" ID="sm1" /&gt;

        &lt;rsweb:ReportViewer ID="ReportViewer1" runat="server"/&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>In the code behind file, I added the following to the <b>Page_Load</b> event.</p>
<pre class="brush:c-sharp;">if (!IsPostBack)
{
    ReportViewer1.ProcessingMode = ProcessingMode.Remote;

    ReportViewer1.ServerReport.ReportServerUrl =
        new Uri("http://localhost/reportserver");

    ReportViewer1.ServerReport.ReportPath = "/test/test_report";
}
</pre>
<p>After saving, I loaded the page in a web browser and received the following error.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer4.png" alt="" title="ReportViewer4" width="408" height="342" class="aligncenter size-full wp-image-879" /></p>
<p>It&#8217;s not often an error message tells you exactly what to do to fix the problem.&nbsp;&nbsp;I added the following lines to the <b>web.config</b> file.</p>
<pre class="brush:xml;">&lt;system.webServer&gt;
    &lt;handlers&gt;
        &lt;add name="ReportViewerWebControlHandler"
                preCondition="integratedMode" verb="*"
                path="Reserved.ReportViewerWebControl.axd"
                type="Microsoft.Reporting.WebForms.HttpHandler,
                Microsoft.ReportViewer.WebForms,
                Version=10.0.0.0, Culture=neutral,
                PublicKeyToken=b03f5f7f11d50a3a" /&gt;
    &lt;/handlers&gt;
&lt;/system.webServer&gt;
</pre>
<p>After refreshing the page I saw another error.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer5.png" alt="" title="ReportViewer5" width="452" height="159" class="aligncenter size-full wp-image-880" /></p>
<p>This is simple enough to fix though.&nbsp;&nbsp;I went back to the report server web site and added <b>APPPOOL\DefaultAppPool</b> as a user with the <b>Browser</b> role.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer6.png" alt="" title="ReportViewer6" width="423" height="118" class="aligncenter size-full wp-image-881" /></p>
<p>Now on refreshing the web page again, the report is displayed.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer71.png" alt="" title="ReportViewer7" width="451" height="294" class="aligncenter size-full wp-image-922" /></p>
<p>I don&#8217;t really want the toolbar to be displayed and would like the report to render without clipping so I added the following to lines.</p>
<pre class="brush:csharp">ReportViewer1.ShowToolBar = false;

ReportViewer1.SizeToReportContent = true;
</pre>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/02/ReportViewer81.png" alt="" title="ReportViewer8" class="aligncenter size-full wp-image-925" /></p>
<p>The report above didn&#8217;t require any parameters but if it did I could have added them using the code below.</p>
<pre class="brush:c-sharp">// Single Parameter
ReportParameter p = new ReportParameter("invoice_id","2");

ReportViewer1.ServerReport.SetParameters(p);

// Multiple Parameters 

List&lt;ReportParameter&gt; l = new List&lt;ReportParameter&gt;();

l.Add(new ReportParameter("invoice_id","2"));
l.Add(new ReportParameter("user_id","7623"));
ReportViewer1.ServerReport.SetParameters(l);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2012/02/22/reportviewer-control-and-asp-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MDX queries and T4 Templates</title>
		<link>http://dannyquinn.co.uk/2012/01/26/mdx-queries-and-t4-templates/</link>
		<comments>http://dannyquinn.co.uk/2012/01/26/mdx-queries-and-t4-templates/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 20:48:31 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[SSAS]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[MDX]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=830</guid>
		<description><![CDATA[When I need to display data from a cube on a web page, I usually store the MDX query in a text file and make this file part of a resource file.&#160;&#160;This allows me to store the MDX in a readable format. In the image below, I have two files in the App_GlobalResources folder.&#160;&#160;The first [...]]]></description>
			<content:encoded><![CDATA[<p>When I need to display data from a cube on a web page, I usually store the MDX query in a text file and make this file part of a resource file.&nbsp;&nbsp;This allows me to store the MDX in a readable format.</p>
<p>In the image below, I have two files in the <b>App_GlobalResources</b> folder.&nbsp;&nbsp;The first is the resource file and the second the text file the contains the query.&nbsp;&nbsp;One the left you can see that the text file is embedded in the resource file.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/01/MDXT4_1.png" alt="" title="MDXT4_1" width="476" height="201" class="aligncenter size-full wp-image-834" style="border:none;" /></p>
<p>The <b>MyQuery.txt</b> file may contain something simple such as</p>
<pre class="brush:sql;">SELECT
    {
        [Measures].[Reseller Sales Amount]
    } ON COLUMNS,
    {
        [Date].[Calendar].[Month].&#038;[&lt;&lt;YEAR&gt;&gt;]&#038;[&lt;&lt;MONTH&gt;&gt;]
    } ON ROWS
FROM
    [Adventure Works]
</pre>
<p>To use this script in code you can simply access the resource as below.
<pre class="brush: c-sharp;">string mdx = Resources.MDX.MyQuery;

AdomdCommand com = new AdomdCommand(mdx,cxn);
</pre>
<p>Notice that the <b>Date</b> hierarchy contains the strings <b>&lt;&lt;YEAR&gt;&gt;</b> and <b>&lt;&lt;MONTH&gt;&gt;</b>.&nbsp;&nbsp;I do this to create place holders so that I can specify different values to adjust the query.</p>
<pre class="brush: c-sharp;">string mdx = Resources.MDX.MyQuery;

mdx = mdx.Replace("&lt;&lt;YEAR&gt;&gt;","2008");
mdx = mdx.Replace("&lt;&lt;MONTH&gt;&gt;","3");
</pre>
<p>I read an article about T4 templates the other day and wondered if I could replace my text file resources with these templates.&nbsp;&nbsp;That&#8217;s not to say there is anything wrong with the method above.&nbsp;&nbsp;I have been using this method for quite a while now and haven&#8217;t had any problems.&nbsp;&nbsp;Really I just wanted to try it in order to learn a bit more about <a href="http://msdn.microsoft.com/en-us/library/bb126445.aspx" target="_blank">T4 templates</a>.</p>
<p>To start with I add a new <b>Preprocessed Text Template</b> to my web project.&nbsp;&nbsp;I choose to store these templates in a specific folder in <b>App_Code</b> but you don&#8217;t have to.</p>
<p><a href="http://dannyquinn.co.uk/wp-content/uploads/2012/01/MDXT4_2.png"><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/01/MDXT4_2-300x169.png" alt="" title="MDXT4_2" width="300" height="169" class="aligncenter size-medium wp-image-841" /></a></p>
<p>When you add a template (using Visual Studio 2010), the IDE creates two files, one with a .tt extension and another with a .cs extension.&nbsp;&nbsp;The code in the .cs file is auto-generated and a comment at the top advises against changing this file directly.</p>
<p>To start with the MyQuery.tt file only contains one line, a directive.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/01/MDXT4_3.png" alt="" title="MDXT4_3" width="644" height="169" class="aligncenter size-full wp-image-848" /></p>
<p>The query above contained two placeholders that allowed values to be set a runtime and I want to be able to do the same thing using templates.&nbsp;&nbsp;There are a couple of ways to do this.&nbsp;&nbsp;First then with parameters.</p>
<pre class="brush: sql;">&lt;#@ template language="c#" #&gt;
&lt;#@ parameter name="Year" type="System.Int32"#&gt;
&lt;#@ parameter name="Month" type="System.Int32"#&gt;
SELECT
    {
        [Measures].[Reseller Sales Amount]
    } ON COLUMNS,
    {
        [Date].[Calendar].[Month].&#038;[&lt;#=Year#&gt;]&#038;[&lt;#=Month#&gt;]
    } ON ROWS
FROM
    [Adventure Works]
</pre>
<p>When I save the template file Visual Studio will create a class in the .cs file for me that will render my template.&nbsp;&nbsp;There is actually quite a lot of code generated and I believe this is done so that you don&#8217;t have to distribute the T4 assemblies with the code.</p>
<p>Now to use the template just create an instance of this class, set the parameters and call the <b>TransformText()</b> method.&nbsp;&nbsp;If you&#8217;re not sure of the class name, open the .cs file.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2012/01/MDXT4_4.png" alt="" title="MDXT4_4" width="355" height="273" class="aligncenter size-full wp-image-853" /></p>
<pre class="brush: c-sharp;">using MDXTemplates;
...
...
    // Create an object from the class
    MyQuery m = new MyQuery();

    // Set the parameters
    m.Session = new Dictionary&lt;string,object&gt;();

    m.Session.Add("Year",2008);
    m.Session.Add("Month",3);

    // Call Initialize to copy the parameters across.
    m.Initialize();

    // Get the MDX

    string mdx = m.TransformText();
</pre>
<p>Instead of using parameters, you can also add properties and methods to the class (it is marked as <b>partial</b>).&nbsp;&nbsp;First, go back to the <b>MyQuery.tt</b> file and remove the two parameter directives.</p>
<pre class="brush: sql;">&lt;#@ template language="c#" #&gt;
SELECT
    {
        [Measures].[Reseller Sales Amount]
    } ON COLUMNS,
    {
        [Date].[Calendar].[Month].&#038;[&lt;#=Year#&gt;]&#038;[&lt;#=Month#&gt;]
    } ON ROWS
FROM
    [Adventure Works]
</pre>
<p>Next create a new class in the same namespace and with the same name as the generated class (don&#8217;t forget the partial keyword).</p>
<pre class="brush: c-sharp;">namespace MDXTemplates
{
    public partial class MyQuery
    {
        public int Year{get;set;}
        public int Month{get;set;}
    }
}
</pre>
<p>The class can now be used like this</p>
<pre class="brush: c-sharp;">using MDXTemplates;
...
...
    // Create an object from the class
    MyQuery m = new MyQuery();

    m.Year = 2008;
    m.Month = 3;

    string mdx = m.TransformText();
</pre>
<p>Taking this one step further, by adding a constructor to this class&#8230;.</p>
<pre class="brush: c-sharp;">public partial class MyQuery
{
    public MyQuery(int year,int month)
    {
        Year = year;
        Month = month;
    }
    public int Year{get;set;}
    public int Month{get;set;}
}
</pre>
<p>I can now load the MDX in one line.</p>
<pre class="brush: c-sharp;">string mdx = new MyQuery(2008,3).TransformText();</pre>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2012/01/26/mdx-queries-and-t4-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AsyncFileUpload file filter</title>
		<link>http://dannyquinn.co.uk/2012/01/15/asyncfileupload-file-filter/</link>
		<comments>http://dannyquinn.co.uk/2012/01/15/asyncfileupload-file-filter/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 12:09:35 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[AJAX]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=820</guid>
		<description><![CDATA[The AsyncFileUpload control (part of the AjaxControlToolkit) does not expose a method that enables you to limit or filter the types of files that can be uploaded. You could add logic to the server side event UploadedComplete to check the file extension prior to saving the file but you would need to upload the file [...]]]></description>
			<content:encoded><![CDATA[<p>The <b>AsyncFileUpload</b> control (part of the <b>AjaxControlToolkit</b>) does not expose a method that enables you to limit or filter the types of files that can be uploaded.</p>
<p>You could add logic to the server side event <b>UploadedComplete</b> to check the file extension prior to saving the file but you would need to upload the file before it could be checked.</p>
<p>Instead perform the test in the client side event <b>OnClientUploadStarted</b>.&nbsp;&nbsp;At first I thought that returning &#8216;false&#8217; from this function would prevent the file uploading, it doesn&#8217;t.&nbsp;&nbsp;You need to raise an error within this function to stop the file upload.&nbsp;&nbsp;When the error occurs the <b>OnClientUploadError</b> function is called (if you have created a handler for this event).</p>
<pre class="brush: xml;highlight:[14,15,16,17,18,19,20]">&lt;head&gt;
    &lt;script type="text/javascript"&gt;

        function uploadComplete(sender,args)
        {
            var file = args.get_fileName();
            // Do something here to indicate the file has been uploaded.
        }

        function uploadStarted(sender,args)
        {
            var file = args.get_fileName();

            // File types that should not be uploaded.
            var extensions = "exe|bat|com|msi";

            if (new RegExp("("+extensions+")$").test(file))
            {
                throw(new Error());
            }
        }

        function uploadError(sender,args)
        {
            // Do something to indicate error
        }
    &lt;/script&gt;

    &lt;script runat="server"&gt;
        void afu_UploadComplete(object sender,AsyncFileUploadEventArgs e)
        {
            // Save File
        }
        void afu_UploadFileError(object sender,AsyncFileUploadEventArgs e)
        {
            // Handle Error
        }
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form runat="server&gt;
        &lt;ajx:ToolkitScriptManager runat="server" id="sm1"/&gt;

        &lt;ajx:AsyncFileUpload runat="server" id="afu"
            OnUploadComplete="afu_UploadComplete"
            OnUploadFileError="afu_UploadFileError"
            OnClientUploadStarted="uploadStarted"
            OnClientUploadComplete="uploadComplete"
            OnClientUploadError="uploadError"
            UploaderStyle="Modern"
        /&gt;

    &lt;/form&gt;
&lt;/body&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2012/01/15/asyncfileupload-file-filter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database Mirroring</title>
		<link>http://dannyquinn.co.uk/2012/01/14/database-mirroring/</link>
		<comments>http://dannyquinn.co.uk/2012/01/14/database-mirroring/#comments</comments>
		<pubDate>Sat, 14 Jan 2012 14:36:00 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=763</guid>
		<description><![CDATA[It&#8217;s not very often that I need to setup database mirroring and because it&#8217;s something I do rarely, I can never remember the exact syntax.&#160;&#160;In the code below ServerP is the Principle, ServerM the mirror and ServerW the witness. -- On ServerP CREATE ENDPOINT [Mirror] AUTHORIZATION [domain\sqladmin] STATE=STARTED AS TCP (LISTENER_PORT=7777, LISTENER_IP=ALL) FOR DATA_MIRRORING ( [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s not very often that I need to setup database mirroring and because it&#8217;s something I do rarely, I can never remember the exact syntax.&nbsp;&nbsp;In the code below <b>ServerP</b> is the Principle, <b>ServerM</b> the mirror and <b>ServerW</b> the witness.</p>
<pre class="brush: sql;">-- On ServerP
CREATE ENDPOINT [Mirror] AUTHORIZATION [domain\sqladmin]
    STATE=STARTED
    AS TCP (LISTENER_PORT=7777, LISTENER_IP=ALL)
    FOR DATA_MIRRORING (
        ROLE=PARTNER,
        AUTHENTICATION=WINDOWS NEGOTIATE,
        ENCRYPTION=REQUIRED ALGORITHM RC4
    )
GO
BACKUP DATABASE [DatabaseName] TO DISK 'C:\SomeFolder\DBName.Bak'
GO
BACKUP LOG [DatabaseName] TO DISK 'C:\SomeFolder\DBName.trn'
GO
</pre>
<p>Copy the .bak and .trn file to <b>ServerM</b> and then execute the following.</p>
<pre class="brush: sql;">-- On ServerM
CREATE ENDPOINT [Mirror] AUTHORIZATION [domain\sqladmin]
    STATE=STARTED
    AS TCP (LISTENER_PORT=7777, LISTENER_IP=ALL)
    FOR DATA_MIRRORING (
        ROLE=PARTNER,
        AUTHENTICATION_WINDOWS NEGOTIATE,
        ENCRYPTION=REQUIRED ALGORITHM RC4
    )
GO
CREATE DATABASE [DatabaseName]
GO
RESTORE DATABASE [DatabaseName]
    FROM DISK='C:\SomeFolder\DBName.bak'
    WITH NORECOVERY, REPLACE
GO
RESTORE LOG [DatabaseName]
    FROM DISK='C:\SomeFolder\DBName.trn'
    WITH NORECOVERY, REPLACE
GO
ALTER DATABASE [DatabaseName] SET PARTNER='TCP://ServerP:7777';
GO
</pre>
<p>On the Witness Server <b>ServerW</b> execute the following.</p>
<pre class="brush: sql;">-- On ServerW
CREATE ENDPOINT [Mirror]
    AUTHORIZATION [domain\sqladmin]
    STATE=STARTED
    AS TCP (LISTENER_PORT=7777,LISTENER_IP=ALL)
    FOR DATA_MIRRORING (
        ROLE=WITNESS,
        AUTHENTICATION=WINDOWS NEGOTIATE,
        ENCRYPTION=REQUIRED ALGORITHM RC4
    )
GO
</pre>
<p>Finally, back on the principle server <b>ServerP</b> execute these two commands.</p>
<pre class="brush: sql;">-- On ServerP
ALTER DATABASE [DatabaseName] SET PARTNER='TCP://ServerM:7777';
GO
ALTER DATABASE [DatabaseName] SET WITNESS='TCP://ServerW:7777';
GO
</pre>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2012/01/14/database-mirroring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell &#8211; Processing Production SSAS Databases</title>
		<link>http://dannyquinn.co.uk/2011/12/27/powershell-processing-production-ssas-databases/</link>
		<comments>http://dannyquinn.co.uk/2011/12/27/powershell-processing-production-ssas-databases/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 11:10:08 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Powershell]]></category>
		<category><![CDATA[SSAS]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=701</guid>
		<description><![CDATA[In an earlier post I demonstrated a method I use to update development SSAS databases using powershell.  While this is okay for development servers it doesn&#8217;t really work with production boxes containing millions of rows of data. Generally when I refresh a cube, the only data that will have changed relates to the most recent month or [...]]]></description>
			<content:encoded><![CDATA[<p>In an earlier post I demonstrated a method I use to update development <a href="http://dannyquinn.co.uk/2011/09/08/powershell-processing-ssas-databases/" target="_new">SSAS databases using powershell</a>.  While this is okay for development servers it doesn&#8217;t really work with production boxes containing millions of rows of data.</p>
<p>Generally when I refresh a cube, the only data that will have changed relates to the most recent month or couple of months and so it doesn&#8217;t really make a lot of sense to perform a full refresh each day on every measure group.</p>
<p>Before you can apply different processing methods to an individual measure group, you need to partition the measure group.  In my scenario it made sense to partition each measure group into calendar quarters and this meant that on a daily basis I could perform a full update on the partitions containing the current and previous quarter data and default processing to the remaining partitions.  I also decided that once a week I would perform a full update to all the partitions.</p>
<p>Read more on <a href="http://dannyquinn.co.uk/2011/10/22/ssas-partitions-slices/" target="_new">creating partitions and slices in measure groups.</a></p>
<p>Okay, so I have a measure group named Sales.   I have partitioned the data into calendar quarters (by the Sale Date attribute) and added slice information to each partition.  For example the slice for the current quarter looks like <b>[Sale Date].[Quarter Key].&amp;[201104]</b>.</p>
<p>The first thing my Powershell script needs to do is determine the names of the two quarters that will be processed fully.</p>
<pre class="brush: csharp;"># Create any array to hold the quarter strings
$quarters = "","";

# Determine which quarter we are currently in.
[int] $q = ((get-date).Month+1)/3);

# Create the strings holding the quarter information.
$quarters[0] = "&#038;["+(get-date).Year.ToString()+$q.ToString().PadLeft(2,'0')+"]";

# If current quarter is 1 then we also need Q4 of last year.
if ($q -eq 1)
{
    $quarters[1] = "&#038;["+((get-date).Year-1).ToString()+"04]";
}
else
{
    $quarters[1] = "&#038;["+((get-date).Year).ToString()+
        ($q-1).ToString().PadLeft(2,'0')+"]";
}
</pre>
<p>If you test this script $quarters[1] and [2] should contain <b>&#038;[201104]</b> and <b>&#038;[201103]</b>.&nbsp;&nbsp;Any partition that ends with either of these strings will have Full processing applied.&nbsp;&nbsp;I chose to do it this way as I have several measure groups all partitioned into calendar quarters but the slice attribute is different on each.&nbsp;&nbsp;However all the slices end with the string <b>&#038;[YYYYQQ]</b>.</p>
<p>The next part of the script connects to the database and processes the dimensions.</p>
<pre class="brush: csharp;"># Connect to SSAS database
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.AnalysisServices");

$server = new-object Microsoft.AnalysisServices.Server;
$server.connect("MY_SSAS_SERVER");

$database = $server.databases["MY_SSAS_DATABASE"];

# Process the dimensions - if you perform a full update on a dimension
# then you have to perform full updates on related measure groups.
# I check the day of the week and only perform a full update on Saturdays

$database.dimensions | foreach-object
{
    if ((get-date).DayOfWeek -eq 'Saturday')
    {
        $_.Process("ProcessFull");
    }
else
    {
        $_.Process("Process Default");
    }
}</pre>
<p>Finally process each measure group.&nbsp;&nbsp;If the day is Saturday then just perform a full update against each partition (all measure groups have at least one partition).&nbsp;&nbsp;If is not Saturday then look at each partition and if the slice property is not null and ends with either of a values in the $quarters[] array, apply a <b>ProcessFull</b> otherwise <b>ProcessDefault</b>.</p>
<pre class="brush: csharp;"># Iterate the cubes
$database.cubes | foreach-object
{
    # Iterate each measure group
    $_.MeasureGroups | foreach-object
    {
        $_.Partitions | foreach-object
        {
            if ((get-date).DayOfWeek -eq 'Saturday')
            {
                $_.Process("ProcessFull");
            }
            else
            {
                if ($_.Slice -ne $Null -and ($_.Slice.EndsWith($quarters[0])
                        -or ($_.Slice.EndsWith($quarters[1])))
                {
                    $_.Process("ProcessFull");
                }
                else
                {
                    $_.Process("ProcessDefault");
                }
            }
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2011/12/27/powershell-processing-production-ssas-databases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL 2012 &#8211; Windowed Functions</title>
		<link>http://dannyquinn.co.uk/2011/12/26/sql-2012-windowed-functions/</link>
		<comments>http://dannyquinn.co.uk/2011/12/26/sql-2012-windowed-functions/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 12:27:15 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQL 2012]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=637</guid>
		<description><![CDATA[I recently installed a copy of SQL2012 RC0 and wanted to look at the new language features that have been added.&#160;&#160;In particular the improvements to the OVER clause caught my attention as I could think of a scenario where this would be useful. Back in March of this year I created a blog entry called [...]]]></description>
			<content:encoded><![CDATA[<p>I recently installed a copy of SQL2012 RC0 and wanted to look at the new language features that have been added.&nbsp;&nbsp;In particular the improvements to the <b>OVER</b> clause caught my attention as I could think of a scenario where this would be useful.</p>
<p>Back in March of this year I created a blog entry called <b><a href="http://dannyquinn.co.uk/2011/03/16/iterative-updates/">Iterative Updates</a></b> that demonstrated a method of using a <b>common table expression</b> to perform updates to a set of rows, where the updated values where dependent on the values in earlier rows.</p>
<p>In that acticle I used the example of updating mileage lines with a cost.&nbsp;&nbsp;The following is a snippet from the original post.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/10/IterativeUpdate1.png" alt="" title="IterativeUpdate1" width="508" height="139" class="aligncenter size-full wp-image-130" style="border:none;" /></p>
<p><i>On both of the mileage rows I need to update the claim amount column with the total that should be paid.  For mileage less that 10K, say it’s 40p per mile and 25p after that.  If I processed the rows one at a time I would start the first row, since the user has already claimed 9,975 miles only a further twenty five will be payable at the higher rate and the remainder at the lower rate.</i></p>
<p>The CTE based query was approximately 40 lines long and I was interested to see if I could achieve the same result using the improved <b>OVER</b> clause and if I could reduce the amount of code required.</p>
<p>After 30 minutes or so of trying different approaches and coming up with wrong answers, I came up with the following query that gave the expected results.</p>
<pre class="brush: sql;highlight:[19,20,21];">DECLARE
    @PreviousMiles      INT = 9975,
    @ClaimID            INT = 324

UPDATE
    C
SET
    ClaimAmount = CASE
        WHEN C.Mileage+C.PrevMiles&lt;10000 THEN (0.4 * Mileage)
        WHEN C.PrevMiles&gt;=10000 THEN (0.25 * Mileage)
        ELSE (0.4 * (10000-C.PrevMiles))+(0.25 * (C.Mileage+C.PrevMiles-10000))
    END
FROM
    (
        SELECT
            ClaimAmount,
            ClaimLineID,
            Mileage,
            @PreviousMiles+ISNULL(SUM(Mileage) OVER (
                ORDER BY ClaimNo ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
            ),0) AS PrevMiles
        FROM
            dbo.ClaimLine
        WHERE
            ClaimID = @ClaimID AND Mileage!=0
    ) AS C
</pre>
<p>So how does this work?&nbsp;&nbsp;Well for each row containing mileage I need to know how many miles have already been used.&nbsp;&nbsp;For the first row thats easy, its just the value contained in the @PreviousMiles variable.&nbsp;&nbsp;For each following row I need the take the @PreviousMiles variable and add any mileage used on previous lines.</p>
<p>At first I started with a query similar to this.</p>
<pre class="brush:sql;">DECLARE @PreviousMiles INT = 9975

SELECT
    @ClaimLineID,
    @Mileage,
    @PreviousMiles,
    @PreviousMiles+SUM(Mileage) OVER (ORDER BY ClaimNo ROWS UNBOUNDED PRECEDING)
FROM
    dbo.ClaimLine
WHERE
    Mileage!=0
</pre>
<p>This created the result below.&nbsp;&nbsp;The forth column shows the result of the <b>OVER</b> clause.&nbsp;&nbsp;You can see that the columns value is made up from the @PreviousMileage amount added to the mileage for each claim line and the previous claim line.&nbsp;&nbsp;i.e. ClaimLineID 1, is 30+9975 = 10005 whereas ClaimLineID 2, is 30+35+9975.</p>
<p><b>ROWS UNBOUNDED PRECEDING</b> sets the scope of the <b>SUM()</b> function to allow the rows prior to the current row (and the current row) based on the <b>ORDER BY</b> clause.&nbsp;&nbsp;In fact the statement is equivalent to <b>ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW</b>.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Over1.png" alt="" title="Over1" width="386" height="94" class="aligncenter size-full wp-image-661" style="border:none;"/></p>
<p>Not quite right though, as I need the 4th column to indicate the mileage used prior to the current row.&nbsp;&nbsp;I quickly changed the line to subtract the current mileage.</p>
<pre class="brush: sql;">@PreviousMiles+SUM(Mileage) OVER (ORDER BY ClaimNo ROWS UNBOUNDED PRECEDING)-Mileage</pre>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Over2.png" alt="" title="Over2" width="385" height="93" class="aligncenter size-full wp-image-664" style="border:none;"/></p>
<p>The results were now correct but I didn&#8217;t really like the query.&nbsp;&nbsp;The good news is as well as using <b>UNBOUNDED PRECEDING/FOLLOWING</b> and <b>CURRENT ROW</b> you can also indicate as offset for </b>PRECEDING/FOLLOWING</b>.</p>
<pre class="brush: sql;">@PreviousMiles+ISNULL(SUM(Mileage) OVER (ORDER BY ClaimNo ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0)</pre>
<p>I have wrapped the <b>SUM() OVER()</b> clause in an <b>ISNULL</b> function as the first row will not have a <b>1 PRECEDING</b> row and @PreviousMiles+NULL will always be NULL.</b></p>
<p>From here the rest of the code is pretty straight forward.</p>
<p>In this example I was only updating one claim but the code could be adapted to update multiple claims by using the <b>PARTITION BY</b> clause.</p>
<pre class="brush: sql;">SUM(Mileage) OVER (PARTITION BY ClaimID ORDER BY ClaimNo
    ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)</pre>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2011/12/26/sql-2012-windowed-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maintaining scroll position on postbacks.</title>
		<link>http://dannyquinn.co.uk/2011/12/16/maintaining-scroll-position-on-postbacks/</link>
		<comments>http://dannyquinn.co.uk/2011/12/16/maintaining-scroll-position-on-postbacks/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 21:27:50 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[JQuery]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=586</guid>
		<description><![CDATA[Whenever I create web pages with areas of scrollable content I want to ensure the current scroll position is maintained when a postback occurs (regardless if it is a full or partial postback). As per the screen shot below, I have created a simple web page containing a div with the style attribute overflow:scroll.&#160;&#160;The button [...]]]></description>
			<content:encoded><![CDATA[<p>Whenever I create web pages with areas of scrollable content I want to ensure the current scroll position is maintained when a postback occurs (regardless if it is a full or partial postback).</p>
<p>As per the screen shot below, I have created a simple web page containing a <b>div</b> with the style attribute <b>overflow:scroll</b>.&nbsp;&nbsp;The button just causes a postback to occur (there is no code within the event handler).</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/ScrollPostback.png" alt="" title="ScrollPostback" width="335" height="197" class="aligncenter size-full wp-image-587" /></p>
<p>To ensure the scroll bars remain in the same position, I use two hidden fields (one for the vertical and another for the horizontal scroll) and a small JQuery script.</p>
<p>The code below uses an update panel to create a partial postback but this method works on full postbacks as well.</p>
<p><i>Notice that the hidden fields are initialised to zero, this is important as the JQuery script that follows will attempt to set the scroll positions to the values held within these fields on every page load (including the first).</i></p>
<pre class="brush: xml;">&lt;asp:ScriptManager runat="server" id="sm1"/&gt;

&lt;asp:HiddenField runat="server" id="hfScrollTop" Value="0"/&gt;
&lt;asp:HiddenField runat="server" id="hfScrollLeft" Value="0"/&gt;

&lt;asp:UpdatePanel runat="server" id="upTest"&gt;
    &lt;ContentTemplate&gt;

        &lt;div id="myDiv" style="width:300px;height:150px;overflow:scroll;"&gt;
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua.
            Ut enim ad minim veniam, quis nostrud exercitation ullamco
            ....
        &lt;/div&gt;

        &lt;asp:Button runat="server" id="btnPost" Text="Post" OnClick="btnPost_Click"/&gt;
    &lt;/ContentTemplate&gt;
&lt;/asp:UpdatePanel&gt;
</pre>
<p>To restore the scroll positions, first I need to save each into the two hidden fields and then when the page (or part of) is reloaded, set the scroll bars position according to the hidden field values.</p>
<p>First then to store the values, I use an anonymous function that captures the scroll event.&nbsp;&nbsp;This saves the horizontal and vertical scroll positions into the corresponding hidden fields.</p>
<pre class="brush: js">$("myDiv").scroll(function()
{
    $("#<%=hfScrollTop.ClientID%>").val($(this).scrollTop());
    $("#<%=hfScrollLeft.ClientID%>").val($(this).scrollLeft());
});
</pre>
<p>The client identifiers for <b>runat=&#8221;server&#8221;</b> controls can vary depending on where they are used, .NET ensures the names of controls remain unique by prepending parent id&#8217;s.  For example my hfScrollTop becomes Contents_CRight_hfScrollTop because I am using nested master pages (One ContentPlaceHolder named &#8216;Contents&#8217; and another &#8216;CRight&#8217;).&nbsp;&nbsp;I don&#8217;t want to have to examine the source to determine the id everytime I use this script on a new page and so I use <b>&lt;%= Control.ClientID%&gt;</b> to resolve the client id.</p>
<p>To restore the values after a postback simply reverse the assignments above.</p>
<pre class="brush: js">$("#myDiv").scrollTop($("#&lt;%=hfScrollTop.ClientID %&gt;").val());
$("#myDiv").scrollLeft($("#&lt;%=hfScrollLeft.ClientID %&gt;").val());
</pre>
<p>These two scripts need to be contained within the <b>$(document).ready()</b> function (or a sub-function) and in order for the script to work with partial postbacks you need to wrap the whole thing inside the <b>pageLoad()</b> function.&nbsp;&nbsp;The full script is shown below.</p>
<pre class="brush: js">&lt;script type="text/javascript"&gt;

function pageLoad()
{
    $(document).ready(function()
    {
        // This function will be called whenever the scroll position
        // (Horizontal or Vertical) changes.
        $("#myDiv").scroll(function()
        {
            $("#&lt;%=hfScrollTop.ClientID %&gt;").val($(this).scrollTop());
            $("#&lt;%=hfScrollLeft.ClientID %&gt;").val($(this).scrollLeft());
        });

        // As the page loads set the scroll bar positions to the
        // values stored in the hidden fields.
        $("#myDiv").scrollTop($("#&lt;%=hfScrollTop.ClientID %&gt;").val());
        $("#myDiv").scrollLeft($("#&lt;%=hfScrollLeft.ClientID %&gt;").val());
    });
}
&lt;/script&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2011/12/16/maintaining-scroll-position-on-postbacks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamic Forms in ASP.NET Part 3</title>
		<link>http://dannyquinn.co.uk/2011/12/11/dynamic-forms-in-asp-net-part-3/</link>
		<comments>http://dannyquinn.co.uk/2011/12/11/dynamic-forms-in-asp-net-part-3/#comments</comments>
		<pubDate>Sun, 11 Dec 2011 13:20:17 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Server Controls]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=532</guid>
		<description><![CDATA[In the first post in this series I looked at the database tables and procedures, in the second the classes that make up the question controls.&#160;&#160;In this final part I will build the Survey class and show how to use it on a web page. Link to Part 1&#160;&#160;Link to Part 2 You will recall [...]]]></description>
			<content:encoded><![CDATA[<p>In the first post in this series I looked at the database tables and procedures, in the second the classes that make up the question controls.&nbsp;&nbsp;In this final part I will build the Survey class and show how to use it on a web page.</p>
<p><a href="http://dannyquinn.co.uk/2011/12/08/dynamic-forms-in-asp-net/">Link to Part 1</a>&nbsp;&nbsp;<a href="http://dannyquinn.co.uk/2011/12/09/dynamic-forms-in-asp-net-part-2/">Link to Part 2</a></p>
<p>You will recall from the last post that each of the question classes inherited from <b>QuestionBase</b> which itself inherited from <b>TableRow</b>.&nbsp;&nbsp;The <b>Survey</b> class will therefore inherit from <b>Table</b>.</p>
<p>There are only three properties for this class <b>PersonID</b>, <b>SurveyID</b> and <b>ValidationGroup</b>.&nbsp;&nbsp;The first two are needed to retrieve the correct records from the database while the later is used to setup the correct validation group.&nbsp;&nbsp;In this first code snippet I have only included the boiler plate code.&nbsp;&nbsp;I will describe the methods <b>CreateControlHierarchy()</b> and <b>Save()</b> below.</p>
<pre class="brush: csharp;">namespace DQ.WebControls
{
    public class Survey : Table, INamingContainer
    {
        public int SurveyID{get;set;}
        public int PersonID{get;set;}
        public string ValidationGroup{get;set;}

        protected override void DataBind(){
            Controls.Clear();
            ChildChildControlState();
            CreateControlHierarchy(true);
            ChildControlsCreated=true;
        }
        protected override void CreateChildControls(){
            Controls.Clear();
            CreateControlHierarchy(false);
        }

        // This method creates the various question classes
        // and loads data as appropriate.
        private void CreateControlHierarchy(bool loadData){
            // TODO
        }

        // Save stores the information entered to the database.
        public void Save(){
            // TODO
        }

        // Helper method to convert DBNull.Value to null.
        private object DbNull(object o){
            return (o==DBNull.Value?null:o);
        }

        // OnInit is used to register the control for control
        // control state and the next two methods Load/Save
        // said state.
        protected override void OnInit(EventArgs e){
            Page.RegisterRequiresControlState(this);
            base.OnInit(e);
        }
        protected override void LoadControlState(object savedState){
            object[] state = savedState as object[];
            base.LoadControlState(state[0]);
            SurveyID = (int)state[1];
            PersonID = (int)state[2];
            ValidationGroup = (string)state[3];
        }
        protected override object SaveControlState(){
            object baseState = base.SaveControlState();
            return new object[] { baseState, SurveyID, PersonID, ValidationGroup };
        }
    }
}
</pre>
<p><b>CreateControlHierarchy()</b> will call the stored procedure <b>dbo.SELECT_SURVEY</b> (from the first post in this series) and create each question class as required.</p>
<pre class="brush: csharp;">private void CreateControlHierarchy(bool loadData)
{
    // Don't process unless parameters have been initialized
    if (PersonID==null || SurveyID==null)
        return; 

    // Create a connection to the database and load the appropriate
    // questions and answers.

    using (SqlConnection sqlConn = new SqlConnection("Data Source Here"))
    using (SqlCommand sqlCom = new SqlCommand("dbo.SELECT_SURVEY",sqlConn))
    {
        sqlConn.Open();

        sqlCom.CommandType = CommandType.StoredProcedure;

        sqlCom.Parameters.Add(new SqlParameter("@SurveyID",SurveyID));

        sqlCom.Parameters.Add(new SqlParameter("@PersonID",PersonID));

        SqlDataReader sqlDR = sqlCom.ExecuteReader();

        // I am not going to show any error handling/checking
        // here 

        // Iterate through the recordset, create and add each
        // question class to the controls collection.

        while (sqlDR.Read())
        {
            // Create a QuestionBase class
            QuestionBase qb;

            // and an object to hold the answer.
            object answer = new object();

            // Use the class field to determine the type of
            // question class to create
            switch (sqlDR["Class"].ToString())
            {
                default:
                case "String":
                    // Create a QuestionString class
                    qb = new QuestionString();
                    // Load the answer from the appropriate db column
                    //
                    // DbNull converts DBNull.Value to null
                    answer = DbNull(sqlDR["VarcharAnswer"]);
                    break;
                case "Date":
                    qb = new QuestionDate();
                    answer = DbNull(sqlDR["DateAnswer"]);
                    break;
                case "Integer":
                    qb = new QuestionInteger();
                    answer = DbNull(sqlDR["IntegerAnswer"]);
                    break;
                case "Double":
                    qb = new QuestionDouble();
                    answer = DbNull(sqlDR["FloatAnswer"]);
                    break;
                case "List":
                    qb = new QuestionList();
                    answer = DbNull(sqlDR["IntegerAnswer"]);
                    break;
                case "Boolean":
                    qb = new QuestionBoolean();
                    answer = DbNull(sqlDR["BooleanAnswer"]);
                    break;
            }

            // Create Unique ID
            qb.ID = sqlDR["QuestionID"].ToString();

            // Load generic parameters
            qb.MaxLength = Convert.ToInt16(sqlDR["MaxLength"]);
            qb.ListID = Convert.ToInt32(sqlDR["ListID"]);
            qb.Mandatory = Convert.ToBoolean(sqlDR["Mandatory"]);
            qb.QuestionText = sqlDR["QuestionText"].ToString();
            qb.ValidationGroup = ValidationGroup;

            // If Databinding load the data.
            if (loadData)
            {
                qb.Answer=answer;
                qb.DataBind();
            }
            Controls.Add(qb);
        }
        sqlConn.Close();
    }
}
</pre>
<p>Finally we have the <b>Save()</b> method</p>
<pre class="brush: csharp;">public void Save()
{
    EnsureChildControls();

    // Create a data connection and initialize a command object.
    using (SqlConnection sqlCon = new SqlConnection("Data Source Here"))
    using (SqlCommand sqlCom = new SqlCommand("dbo.UPDATE_ANSWER",sqlCon))
    {
        sqlCon.Open();
        sqlCommand.CommandType = CommandType.StoredProcedure;

        // Iterate through the child controls (all will be of type
        // QuestionBase), determine the correct database and build
        // a SqlParameter.

        foreach(QuestionBase qb in Controls)
        {
            SqlParameter sqlParam = new SqlParameter();

            sqlParam.Value = (qb.Answer==null || qb.Answer.ToString()==string.Empty
                ?DBNull.Value : questionBase.Answer
            );

            // We have the value of sqlParam now to set the column name
            switch (qb.DataType)
            {
                case UIDataType.Boolean:
                    sqlParam.ParameterName="BooleanAnswer";
                    break;
                case UIDataType.Double:
                    sqlParam.ParameterName="FloatAnswer";
                    break;
                case UIDataType.Date:
                    // Dates are a bit strange so check value again and
                    // convert if needed.
                    sqlParam.ParameterName="DataAnswer";
                    sqlParam.Value=(qb.Answer==null ||
                        qb.Answer.ToString()==string.Empty
                        ?SqlDateTime.Null:Convert.ToDateTime(qb.Answer)
                    );
                    break;
                case UIDataType.Integer:
                    sqlParam.ParameterName = "IntegerAnswer";
                    break;
                case UIDataType.String:
                    sqlParam.ParameterName="VarcharAnswer";
                    break;
            }

            // As we are looping over each record or QuestionClass
            // clear the SqlCommand parameter collection.
            sqlCom.Parameters.Clear();

            // Add parameters
            sqlCom.Parameters.Add(new SqlParameter("@PersonID",PersonID));
            sqlCom.Parameters.Add(new SqlParameter("@SurveyID",SurveyID));
            sqlCom.Parameters.Add(new SqlParameter("@QuestionID",int.Parse(qb.ID)));
            sqlCom.Parameters.Add(sqlParam);

            // Execute the command

            sqlCom.ExecuteNonQuery();
        }
    }
    sqlCon.Close();
}
</pre>
<p>Now to use the control.&nbsp;&nbsp;Ensure you have a reference to the namespace containing the <b>Survey</b> control at the top of page or in your web config.</p>
<pre class="brush: xml;">&lt;form runat="server"&gt;
    &lt;AjaxToolkit:ToolkitScriptManager runat="server" id="sm1"/&gt;

    &lt;dq:Survey runat="server" id="Survey1" ValidationGroup="vgSurvey"/&gt;

    &lt;asp:Button runat="server" id="btnUpdate" Text="Save" OnClick="btnUpdate_Click" ValidationGroup="vgSurvey"/&gt;
&lt;/form&gt;
</pre>
<p>The code behind will look something like this.</p>
<pre class="brush: csharp;">protected void Page_Load(object sender,EventArgs e)
{
    if (!IsPostBack)
    {
        Survey1.PersonID = 1;
        Survey1.SurveyID = 1;
        Survey1.DataBind();
    }
}

protected void btnUpdate_Click(object sender, EventArgs e)
{
    Survey1.Save();
}
</pre>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Web.png" alt="" title="Web" width="479" height="140" class="aligncenter size-full wp-image-479" /></p>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2011/12/11/dynamic-forms-in-asp-net-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamic Forms in ASP.NET Part 2</title>
		<link>http://dannyquinn.co.uk/2011/12/09/dynamic-forms-in-asp-net-part-2/</link>
		<comments>http://dannyquinn.co.uk/2011/12/09/dynamic-forms-in-asp-net-part-2/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 10:10:48 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Server Controls]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=497</guid>
		<description><![CDATA[In a previous post I started looking at a sample application that could dynamically create forms in ASP.NET and then store the user input into a database. In this post I am going to continue by looking at the classes used to generate the web controls. As I mentioned in the first post I took [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://dannyquinn.co.uk/2011/12/08/dynamic-forms-in-asp-net/">a previous post</a> I started looking at a sample application that could dynamically create forms in ASP.NET and then store the user input into a database.</p>
<p>In this post I am going to continue by looking at the classes used to generate the web controls.</p>
<p>As I mentioned in the first post I took the basic ideas from this <a href="http://msdn.microsoft.com/en-us/library/aa479330.aspx" target="_new">article on MSDN by Scott Mitchell (2004)</a>.&nbsp;&nbsp;My first few attempts mirrored this code almost exactly and there is still quite a bit of code in my solution that came from reading this.&nbsp;&nbsp;Just how much, I&#8217;ll leave to you to decide.</p>
<p>One big change I made was to move away from using UserControls as I came across problems with partial page rendering and had to rely on nasty hacks to get the forms to work properly.&nbsp;&nbsp;In the above article each question is a user control that implements an interface.&nbsp;&nbsp;Initially I kept the idea of the interface and created a class for each question.&nbsp;&nbsp;It soon became apparent that I had lots of duplicated code and in the early stages of development a simple change would require me to change each <b>Question</b> class.&nbsp;&nbsp;For this reason I moved away from an Interface and created an abstract base class instead.</p>
<p>I decided that my <b>Survey</b> class would inherit from <b>Table</b>, and each <b>Question</b> from <b>TableRow</b> (This just helps to keep the layout neat).&nbsp;&nbsp;The class diagram is displayed below.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Classes.png" alt="" title="Classes" width="534" height="506" class="aligncenter size-full wp-image-500" /></p>
<p>The <b>QuestionBase</b> class has two abstract properties and one astract method that classes inheriting must implement.  <b>DataType</b> &#8211; which is an enumeration, this is used to determine which column in the Answer table to read / update.&nbsp;&nbsp;<b>PostBackControl</b> &#8211; The base class handles the LoadPostData event and in the default implementation it also creates a required field validator (if the mandatory flag for a question a set).&nbsp;&nbsp;In order to do both of these things the class need to know which control to attach to.&nbsp;&nbsp;The method is <b>CreateAnswerCell()</b> &#8211; Each class is responsible for rendering the controls it needs to create the question control and required validators (other than the required validator previously mentioned).</p>
<p>You can also override the method <b>CreateQuestionCell()</b> and <b>CreateValidatorCell()</b> if you don&#8217;t want the base implementation or you can override <b>CreateControlHierarchy()</b> if you want the child classes to control the rendering of the entire TableRow.</p>
<p>Okay, it will probably make more sense with the code, so here is the implementation of <b>QuestionString</b>.</p>
<pre class="brush: csharp;">namespace DQ.WebControls
{
    public class QuestionString : QuestionBase
    {
        private TextBox textBox;

        public override UIDataType DataType{get{return UIDataType.String;}}

        protected override Control PostBackControl{get{return textBox;}}

        protected override void CreateAnswerCell(bool loadData)
        {
            TableCell tcAnswer = new TableCell();

            textBox = new TextBox();
            textBox.ID = "textbox";
            textBox.MaxLength=MaxLength;

            tcAnswer.Controls.Add(textBox);

            if (loadData)
                textBox.Text=(Answer==null?string.Empty:Answer.ToString());

           Controls.Add(tcAnswer);
        }
    }
}
</pre>
<p>Seems pretty simple really.&nbsp;&nbsp;All the real work is done in <b>QuestionBase</b>.</p>
<pre class="brush: csharp;">namespace DQ.WebControls
{
    public abstract class QuestionBase : TableRow,
            INamingContainer, IPostBackDataHander
    {
        // Most questions will have the option of being mandatory and so
        // it makes sense to place the validator in the base class.
        protected RequiredFieldValidator rfv;

        // Properties
        public string QuestionText{get;set;}
        public string ValidationGroup{get;set;}
        public int MaxLength{get;set;}
        public int ListID{get;set;}
        public bool Mandatory{get;set;}
        public object Answer{get;set;}

        // Each question is strongly typed.  Each question class
        // must provide this information.
        public abstract UIDataType DataType{get;}

        // Each child class should override this property and
        // return the control that will accept input.
        protected abstract Control PostBackControl{get;}

        // The databind method is called when populating
        // the controls with info from the database.
        public override void DataBind()
        {
            base.DataBind();
            Controls.Clear();
            ClearChildControlState();
            CreateControlHierarchy(true);
            ChildControlsCreated=true;
        }

        // This method recreates controls on postback
        protected override void CreateChildControls()
        {
            Controls.Clear();
            CreateControlHierarchy();
        }

        // You can override this method if you want
        // to control the TableRow layout
        protected virtual void CreateControlHierarchy(bool loadData)
        {
            CreateQuestionCell(loadData);
            CreateAnswerCell(loadData);
            CreateValidatorCell(loadData);
        }

        // The question cell is simple.  Just text
        // in a table cell.
        protected virtual void CreateQuestionCell(loadData)
        {
            TableCell tcQuestion = new TableCell();
            tcQuestion.Text = QuestionText;
            Controls.Add(tcQuestion);
        }

        // The answer cell is abstract, child class must
        // provide this implementation.
        protected abstract void CreateAnswerCell(bool loadData);

        // The validator cell is straight forward enough.  It
        // uses the property PostBackControl to attach to the
        // input control.
        protected virtual CreateValidatorCell(bool loadData){
            TableCell tcValidator = new TableCell();

            if (Mandatory){
                rfv = new RequiredFieldValidator();
                rfv.ID = "validator";
                rfv.ControlToValidate = PostBackControl.ID;
                rfv.Display = ValidatorDisplay.Dynamic;
                rfv.ErrorMessage="*";
                rfv.CssClass="ValidationError";
                rfv.ValidationGroup=ValidationGroup;

                tcValidator.Controls.Add(rfv);
            }

            Controls.Add(tcValidator);
        }

        // Register the control for both ControlState and PostBackEvents
        protected override void OnInit(EventArgs e)
        {
            Page.RegisterRequiresPostBack(this);
            Page.RegisterRequiresControlState(this);
            base.OnInit(e);
        }
        // I don't use this method but it has to be implemented.
        void IPostBackDataHandler.RaisePostBackDataChangedEvent(){}

        // LoadPostData retrieves the value entered and stores in the
        // Answer property.
        // The PostBackControl property is used as the key to retrieve
        // the correct value from the collection.
        bool IPostBackDataHandler.LoadPostData(string postKey,NameValueCollection values)
        {
            EnsureChildControls();
            Answer = values[PostBackControl.UniqueID];
            return false;
        }

        // Finally two methods for control state
        protected override void LoadControlState(object savedState)
        {
            object[] state = savedState as object[];
            base.LoadControlState(state[0]);
            Answer = state[1];
        }
        protected override object SaveControlState()
        {
            object baseState = base.SaveControlState();
            return new object[]{baseState,Answer};
        }
    }
}
public enum UIDataType
{
    String,
    Integer,
    Double,
    Date,
    Boolean
}
</pre>
<p><P>Each of the other question classes looks very similar to the <b>QuestionString</b> class and I won&#8217;t show the code for each.&nbsp;&nbsp;I will show two more which implement slightly different behaviour; <b>QuestionDate</b> &#038; <b>QuestionList</b>.  Note &#8211; <b>QuestionDate</b> uses the <b>AjaxControlToolkit</b> controls <b>CalendarExtender</b> and <b>VallidatorCalloutExtender</b>.</p>
<pre class="brush: csharp;">public class QuestionDate : QuestionBase
{
    private TextBox textBox;
    private CalendarExtender ce;
    private CompareValidator cv;
    private ValidatorCalloutExtender vce;

    public override UIDataType DataType{get{return UIDataType.Date;}}

    protected override Control PostBackControl{get{return textBox;}}

    protected override CreateAnswerCell(bool loadData){
        TableCell tcAnswer = new TableCell();

        textBox = new TextBox();
        textBox.ID = "textbox";
        textBox.MaxLength=10;
        textBox.Columns=10;

        tcAnswer.Controls.Add(textBox);

        if (loadData){
            textBox.Text=string.Format("{0:dd/MM/yyyy}",Answer);
        }

        // Add a Calendar Extender
        ce = new CalendarExtender();
        ce.ID = "calendar";
        ce.TargetControlID = textBox.ID;
        ce.Format="dd/MM/yyyy";
        ce.PopupPosition = CalendarPosition.TopLeft;

        tcAnswer.Controls.Add(ce);

        // Add a compare validators to enusre input is a valid
        // date.

        cv = new CompareValidator();
        cv.ID = "compare";
        cv.ControlToValidate = textBox.ID;
        cv.Display = ValidatorDisplay.None;
        cv.ErrorMessage = "Invalid date format.  Use dd/MM/yyyy.";
        cv.Operator = ValidationCompareOperator.DataTypeCheck;
        cv.Type = ValidationDataType.Date;
        cv.ValidationGroup = ValidationGroup;

        tcAnswer.Controls.Add(cv);

        // Finally an an extender for the validator.

        vce = new ValidatorCalloutExtender();
        vce.ID = "extender";
        vce.TargetControlID = compareValidator.ID;
        vce.PopupPosition = ValidatorCalloutPosition.Right;

        tcAnswer.Controls.Add(vce);

        Controls.Add(tcAnswer);
    }
}
</pre>
<p><P><b>QuestionList</b> uses a <b>DropDownList</b> control instead of a textbox.&nbsp;&nbsp;It also needs to retrieve the list from the database and override the <b>CreateValidatorCell()</b> method as below.</p>
<pre class="brush: csharp;">public class QuestionList : QuestionBase
{
    private DropDownList dropDownList;

    public override UIDataType DataType{get{return UIDataType.Integer;}}

    protected override Control PostBackControl{get{return dropDownList;}}

    protected override CreateAnswerCell(bool loadData)
    {
        TableCell tcAnswer = new TableCell();

        dropDownList = new DropDownList();
        dropDownList.ID = "dropdown";
        dropDownList.Width=Unit.Pixel(180);

        tcAnswer.Controls.Add(dropDownList);

        // Retrieve list from database.
        using (SqlConnection sqlConn = new SqlConnection("Data Source Here"))
        using (SqlDataAdapter sqlAdp = new SqlDataAdapter("dbo.SELECT_LIST",sqlConn))
        using (DataTable dt = new DataTable())
        {
            sqlAdp.SelectCommand.CommandType=CommandType.StoredProcedure;

            sqlAdp.SelectCommand.Parameters.Add(
                new SqlParameter("@ListID",ListID)
            );

            sqlAdp.Fill(dt);

            // Add a default row to handler NULL values i.e.
            // where the user is yet to make a selection.
            DataRow dr = dt.NewRow();
            dr[0]="0";
            dr[1]="Please Select";
            dt.Rows.Add(dr);

            dropDownList.DataSource = dt;
            dropDownList.DataValueField=dt.Columns[0].ColumnName;
            dropDownList.DataTextField=dt.Columns[1].ColumnName;
            dropDownList.DataBind();
        }

        if (loadData)
        {
            // Select appropriate listitem
            dropDownList.ClearSelection();

            string answer = (Answer==null?"0":Answer.ToString());

            for (int i=0;i&lt;dropDownList.Items.Count;i++)
            {
                if (dropDownList.Items[i].Value==answer)
                {
                    dropDownList.Items[i].Selected=true;
                    break;
                }
            }
       }
       Controls.Add(tcAnswer);
    }

    // Override CreateValidatorCell as we need to add the property
    // InitialValue to the required field validator.
    protected override void CreateValidatorCell(bool loadData)
    {
        // Create the default implementation.
        base.CreateValidatorCell(loadData);

        // if Mandatory is true then the validator exists
        if (Mandatory)
        {
            // Add the property value
            rfv.InitialValue="0";
        }
    }
}
</pre>
<p>In the next (final) post on this subject I will create the <b>Survey</b> Web Control and show how to use the control on a web page.</p>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2011/12/09/dynamic-forms-in-asp-net-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hyper V &amp; Wireless Connections</title>
		<link>http://dannyquinn.co.uk/2011/12/09/hyper-v-wireless-connections/</link>
		<comments>http://dannyquinn.co.uk/2011/12/09/hyper-v-wireless-connections/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 08:07:05 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://dannyquinn.co.uk/?p=559</guid>
		<description><![CDATA[I have a Hyper V server at home for testing different scenarios (well its not really a server just a bog standard desktop pc).&#160;&#160;On this computer I use a wireless card to connect to my router as the pc is no where near any telephone sockets.&#160;&#160;At first I thought I couldn&#8217;t connect the virtual computers [...]]]></description>
			<content:encoded><![CDATA[<p>I have a Hyper V server at home for testing different scenarios (well its not really a server just a bog standard desktop pc).&nbsp;&nbsp;On this computer I use a wireless card to connect to my router as the pc is no where near any telephone sockets.&nbsp;&nbsp;At first I thought I couldn&#8217;t connect the virtual computers to the internet (via wireless) and so used a couple of X10 plugs to route the internet through the powerlines.</p>
<p>However, with a bit of tweaking you can use a wireless connection with the virtual computers.&nbsp;&nbsp;To start with wireless lan is not automatically available on Server 2008 r2, you have to enable the feature.</p>
<p>Open the <b>Server Manager</b>, click on features and then <b>Add Features</b>.&nbsp;&nbsp;In the dialog scroll down to <b>Wireless LAN Service</b> and check the option.&nbsp;&nbsp;Click next followed by install and in a few seconds the wireless service will run running.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Wireless1-300x251.png" alt="" title="Wireless1" width="300" height="251" class="aligncenter size-medium wp-image-560" /></p>
<p>Next, open the <b>Hyper-V Manager</b> and select <b>Virtual Network Manager</b> from the actions pane.&nbsp;&nbsp;Create a new internal network, I just left all the settings as they were.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Wireless2-300x194.png" alt="" title="Wireless2" width="300" height="194" class="aligncenter size-medium wp-image-563" /></p>
<p>If you already have virtual computers created you can change the network of each by editing the settings of each.&nbsp;&nbsp;From the settings dialog, select <b>Network Adapter</b> and then select the newly created internal network from the list.</p>
<p>To complete this task, open Network and Sharing Centre by right clicking the tray icon (or via control panel).&nbsp;&nbsp;Select <b>Change Adapter Settings</b> from the list on the left and then select the Wireless and Internal network items at the same time, right click and select <b>Bridge Connections</b>.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Wireless3-280x300.png" alt="" title="Wireless3" width="280" height="300" class="aligncenter size-medium wp-image-564" /></p>
<p>After a few seconds a new icon will appear in the <b>Network Connections</b> window, similar to the screen shot below.&nbsp;&nbsp;The virtual computers can now use the wireless connection.</p>
<p><img src="http://dannyquinn.co.uk/wp-content/uploads/2011/12/Wireless4.png" alt="" title="Wireless4" width="285" height="234" class="aligncenter size-full wp-image-565" /></p>
]]></content:encoded>
			<wfw:commentRss>http://dannyquinn.co.uk/2011/12/09/hyper-v-wireless-connections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

