Archive

Archive for May, 2009

Error moving SQL Server Integration Services (SSIS) package to a 64bit server

May 23rd, 2009

This week one of our database servers was upgraded to a 64bit Windows platform.  Everything seemed fine until I went to execute an SSIS package.   I opened the package with dtexecui.exe and received the following gift after hitting the execute button.

The new connection manager could not be created.
Additional information: Exception from HRESULT: 0xC0010014
(Microsoft.SQLServer.DTSRuntimeWrap)

After much searching, installing Business Business Intelligence Development Studio (BIDS) to debug, and heartache I ended up finding a form post entitled “MS SQL 2005 SP2 x64 & SSIS Packages” about several key DLLs that may not have been properly registered at setup.  This saved my day!  I registered the problem child DLL using the following command and life was good again.

regsvr32 "\Program Files (x86)\Microsoft SQL Server\90\DTS\Binn\DTS.dll"

Web Development , ,

JavaScript Variable Pattern

May 20th, 2009

To help make writing and maintaining JavaScript easier in ASP.NET I have started to use a pattern that isolates the JavaScript variables away from the core script.  By doing this I can avoid a bunch of string concatenation in my server side code and embedded code blocks in my .aspx page when rendering dynamic JavaScript.  The core JavaScript can be placed into a .js file.  The ASP.NET page is now only responsible for rendering a list of updated variables that the core script expects.

To demonstrate consider a set of jQuery tabs that contains forms on each tab.  When a form is submitted from a particular tab the tab should be selected after the form posts back.  Using embedded code blocks the JavaScript would be. 

<script type="text/javascript">
    jQuery(function($) {
        $("#tabs").tabs();
        $("#tabs").tabs('select', <%=selectedTab %>);
    });
</script>

While this looks pretty clean it prevents us from putting this JavaScript into a .js file.  Applying the variable pattern the JavaScript can be refactored to the following and placed into a .js file.

jQuery(function($) {
    $("#tabs").tabs();
    $("#tabs").tabs('select', selectedTab);
});

The page is now only responsible for rendering the ‘selectedTab’ variable.

<script type="text/javascript">
    var selectedTab = 3;
</script>

I have created a JavaScriptVariable class to assist in rendering the JavaScript variables.   The JavaScript block is rendered to the page using ScriptManager.RegisterStartupScript to ensure the variable are available to scripts.  In addition, the ‘JavaScriptVariables’ member variable and the RenderJavaScriptVaraibles() method could be added to a base Paqe class.  Here is an example using JavaScriptVariable to render the variables for example above.

    IList<JavaScriptVariable> JavaScriptVariables = new List<JavaScriptVariable>();
    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        JavaScriptVariables.Add(new JavaScriptVariable("selectedTab", selectedTab.ToString(), "{0}"));
        ScriptManager.RegisterStartupScript(this, typeof(AspNetDiag), "AspNetDiagVars.js", RenderJavaScriptVariables(), true);
    }

    private string RenderJavaScriptVariables()
    {
        StringBuilder js = new StringBuilder();
        foreach (var jsVar in JavaScriptVariables)
        {
            js.AppendFormat("var {0} = {1};", jsVar.Name, jsVar.GetFormatedValue());
        }
        return js.ToString();
    }

Finally the source for JavaScriptVariable.  

class JavaScriptVariable
{
    public string Name { get; set; }
    public string Value { get; set; }
    public string Format { get; set; }

    public JavaScriptVariable(string name, string value) : this(name, value, "\"{0}\"") { }
    public JavaScriptVariable(string name, string value, string format)
    {
        Name = name;
        Value = value;
        Format = format;
    }

    public string GetFormatedValue()
    {
        return String.Format(Format, Value);
    }
}

Web Development , ,

Calling a button click from JavaScript in ASP.NET

May 12th, 2009

ASP.NET web forms page have a JavaScript method for handling PostBacks called “__doPostBack”.  This function is used to submit button clicks back to the server.

function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}

The cool thing is that you can take advantage of the same methods that the framework uses to generate javascript for button clicks.  Use the following in your code file to generate the JavaScript that performs the PostBack. Using this method will ensure that the proper ClientID for the control is used.

protected string GetLoginPostBack()
{
    return Page.ClientScript.GetPostBackEventReference(btnLogin, string.Empty);
}

Then in the ASPX page add a javascript block.

<script language="javascript">
function btnLogin_Click() {
  <%= GetLoginPostBack() %>;
}
</script>

The final javascript will be rendered like this.

<script language="javascript">
function btnLogin_Click() {
  __doPostBack('btnLogin','');
}
</script>

Now you can use “btnLogin_Click()” from your javascript to submit the button click to the server.

Web Development ,

Optional Parameter Techniques in MS SQL Server

May 8th, 2009

I ran into some nasty SQL today while updating a report at work.  The report accepted several parameters that were optional.  When a parameters value was set to ‘ALL’ then the filter was ignored.   To handle the optional parameters the previous developer had created a set of WHERE statements for each scenario that the parameters could exist as.  Here is the WHERE clause in question.  Each scenario is separated by ‘OR ( BP.BS_Paid = 1 )’.  Good thing there were only three optional parameters.

The nasty WHERE clause: (bear with me on the names in the SQL.  The snippet is from a health care application.)

WHERE   ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( BP.BS_Performed_Date BETWEEN @ProcedurePerformed_From
                                   AND     @ProcedurePerformed_To )
        AND ( SUBSTRING(PS.Site_num, 2, 2) = REPLICATE('0', 2 - LEN(@LCC))
              + @LCC )
        AND ( PS2.Site_num = @Provider )
        OR ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( SUBSTRING(PS.Site_num, 2, 2) = REPLICATE('0', 2 - LEN(@LCC))
              + @LCC )
        AND ( PS2.Site_num = @Provider )
        AND ( @ProcedurePerformed_ALL = 'ALL' )
        OR ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( BP.BS_Performed_Date BETWEEN @ProcedurePerformed_From
                                   AND     @ProcedurePerformed_To )
        AND ( PS2.Site_num = @Provider )
        AND ( @LCC = 'ALL' )
        OR ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( PS2.Site_num = @Provider )
        AND ( @ProcedurePerformed_ALL = 'ALL' )
        AND ( @LCC = 'ALL' )
        OR ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( BP.BS_Performed_Date BETWEEN @ProcedurePerformed_From
                                   AND     @ProcedurePerformed_To )
        AND ( SUBSTRING(PS.Site_num, 2, 2) = REPLICATE('0', 2 - LEN(@LCC))
              + @LCC )
        AND ( @Provider = 'ALL' )
        OR ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( SUBSTRING(PS.Site_num, 2, 2) = REPLICATE('0', 2 - LEN(@LCC))
              + @LCC )
        AND ( @ProcedurePerformed_ALL = 'ALL' )
        AND ( @Provider = 'ALL' )
        OR ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( BP.BS_Performed_Date BETWEEN @ProcedurePerformed_From
                                   AND     @ProcedurePerformed_To )
        AND ( @LCC = 'ALL' )
        AND ( @Provider = 'ALL' )
        OR ( BP.BS_Paid = 1 )
        AND ( FTProc.Description = 'BreastProcedureName' )
        AND ( @ProcedurePerformed_ALL = 'ALL' )
        AND ( @LCC = 'ALL' )
        AND ( @Provider = 'ALL' )

This mess begged to be refactored, so I sketched out my problem on the white board in the office and got some input from the team.  We came up with three techniques for handling optional parameters.

Technique #1. WHERE clause if..then

This technique essentially uses the an OR operator to decide if the parameter is missing.   When the first expression evaluates to true then the second expression is ignored making the parameter optional.

Using this technique the WHERE clause can be refactored to the following.

WHERE    BP.BS_Paid = 1
         AND FProc.TypeID = 13
         AND (@Provider = 'ALL' OR PS2.Site_num = @Provider)
         AND (@ProcedurePerformed_ALL = 'ALL'
              OR (BP.BS_Performed_Date > @ProcedurePerformed_From
                  AND BP.BS_Performed_Date < @ProcedurePerformed_To))
         AND (@LCC = 'ALL'
              OR SUBSTRING(PS.Site_num, 2, 2) = REPLICATE('0', 2 - LEN(@LCC))+ @LCC ))

The WHERE clause is much more maintainable in this version.  In addition,  the filter can use complex expressions, such as, date ranges.

Technique #2. ISNULL or COALESCE operators

This technique requires that the parameter be NULL when ignoring optional parameters.   The COALESCE operator will use the first NON NULL value.  When a parameter is NULL then the COALESCE uses the column’s value as the second expression, there by setting the column equal to its self.

This technique works fine when evaluating expressions with ‘=’ operator.  However, using the ‘<>’ operators don’t work when comparing a column to itself.   I was forced to comment out the date range expressions are a result of this limitation.

Here is the results from using this technique.

WHERE    BP.BS_Paid = 1
        AND FProc.TypeID = 13
        AND dbo.GetLCCFromSite(PS.Site_num) = COALESCE(@LCC, dbo.GetLCCFromSite(PS.Site_num))
--      AND (BP.BS_Performed_Date > COALESCE(@ProcedurePerformed_ALL,@ProcedurePerformed_From)
--      AND BP.BS_Performed_Date < COALESCE(@ProcedurePerformed_ALL,@ProcedurePerformed_To))
        AND PS2.Site_num = COALESCE(@Provider,  PS2.Site_num)

Technique #3. Dynamic query using sp_executesql

This technique builds a SQL query on the fly and then executes it using sp_executesql.   Dynamically building the SQL allows for WHERE expressions to be omitted all together from the query.  The IF….ELSE construct is used to determine if optional parameters should be included in the query.  I am speculating that this is the best performing technique, because parameters are not even included in the query.

DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);

SET @SQLString = N'WHERE BP.BS_Paid = 1 AND FProc.TypeID = 13';
IF @Provider != 'ALL'
BEGIN
    SET @SQLString = @SQLString + N' AND PS2.Site_num = @xProvider';
END
IF @ProcedurePerformed_ALL != 'ALL'
BEGIN
    SET @SQLString = @SQLString + N' AND (BP.BS_Performed_Date > @xProcedurePerformed_From AND BP.BS_Performed_Date < @xProcedurePerformed_To))';
END
IF @ProcedurePerformed_ALL != 'ALL'
BEGIN
    SET @SQLString = @SQLString + N' AND SUBSTRING(PS.Site_num, 2, 2) = REPLICATE(''0'', 2 - LEN(@xLCC))+ @xLCC ))';
END

SET @ParmDefinition = N'@@xProvider NVARCHAR(10)
                        ,@xProcedurePerformed_From DATETIME
                        ,@xProcedurePerformed_To DATETIME
                        ,@xLCC INT';

EXECUTE sp_executesql @SQLString, @ParmDefinition
                      ,@Provider
                      ,@ProcedurePerformed_From
                      ,@ProcedurePerformed_To
                      ,@LCC;

Web Development

Adding Syntax Highlighter to my blog.

May 1st, 2009

The primary purpose of this blog is to help me catalog stuff that I find useful. I wanted a good way to highlight code snippets as well as make them downloadable when I want to reuse them. Thanks to this great post on hanselman.com I found Syntax Highlighter. Syntax Highlighter will decorate <pre></pre> tags that have been marked with specific CSS classes using JavaScript.  There is no need to have to include HTML markup in the code.   How great is that?!

Here is a test snippet:

function test() : String
{
	return 10;
}

Web Development