<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0" xml:base="http://pierrerebours.com/">
  <channel>
    <title>Pierre Rebours's Log - Thoughts on Engineered Software</title>
    <link>http://pierrerebours.com/</link>
    <description />
    <language>en</language>
          <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/PierreRebours" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="pierrerebours" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">PierreRebours</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
    <title>Coalesce in SAS</title>
    <link>http://pierrerebours.com/blog/coalesce-sas</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/sas"&gt;SAS&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;Coalescing refers to the process of checking the value of each input parameter in the order in which they are listed and returns the first non-missing value. In SAS, the behavior of each of the coalesce functions depends on the processing context, either in a data step or in a &lt;code&gt;PROC SQL&lt;/code&gt; statement. These differences are important to acknowledge, especially when the code is migrated from &lt;code&gt;PROC SQL&lt;/code&gt; to a data step.
&lt;/p&gt;

&lt;p&gt;Suppose, for example, that the following piece of code needs to be modified into a data step:&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;proc sql;
  create table foo2 as
  select coalesce(colum1, column2) as coalesce_column
  from foo;
quit;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
The intuitive approach would be to simply rewrite the code as follows:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;data foo2;
  set foo;
  coalesce_column = coalesce(colum1, column2);
run;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
Although this approach seems to be correct at first glance, it may cause a potential issue: the &lt;code&gt;coalesce&lt;/code&gt; function in the context of a data step treats parameters as numeric values. More specifically, if &lt;code&gt;column1&lt;/code&gt; and &lt;code&gt;column2&lt;/code&gt; are characters, the automatic SAS conversion kicks in by trying to convert these values to numerics. If such a conversion fails, a null value will be passed to the function. Simply switching to the character-compatible function, &lt;code&gt;coalescec&lt;/code&gt;, may still have some side-effects as we will demonstrate in the following sections.
&lt;/p&gt;

&lt;!--break--&gt;

&lt;p&gt;This article is therefore intended to review the behavior of the various &lt;code&gt;coealesce&lt;/code&gt; functions in SAS, and to outline the hurdles when using these functions. All the examples will be driven from the following base table:
&lt;/p&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;%let c_long_var_length = 300;
%let n_short_var_length = 3;
&amp;nbsp;
data root(drop=i character_to_append);
	*character variables;
	c_var_short = 'ABCDEFGHIJKLMN';
&amp;nbsp;
	*create and populate a string which has a size greater than 200;
	length c_var_long $&amp;amp;c_long_var_length;
&amp;nbsp;
	do i = 1 to &amp;amp;c_long_var_length;
		character_to_append = '*';
		if i = 1 then do;
			character_to_append = '&amp;gt;';
		end;
		else if i = &amp;amp;c_long_var_length then do;
			character_to_append = '&amp;lt;';
		end;
		c_var_long = cats(c_var_long, character_to_append);
	end;
&amp;nbsp;
	*numeric variables;
	length n_var_long 8;
	n_var_long = 10.2364545841;
	length n_var_short &amp;amp;n_short_var_length;
	n_var_short = 10;	
run;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
The base table will allow us to study the behaviors of the various &lt;code&gt;coalesce&lt;/code&gt; functions with variables of different lengths and types as summarized as follows:
&lt;/p&gt;

&lt;table border="1" cellpadding="3"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Variable&lt;/th&gt;		&lt;th&gt;Type&lt;/th&gt;	&lt;th&gt;Length&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;c_var_long&lt;/td&gt;		&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;300&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;c_var_short&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;14&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;n_var_long&lt;/td&gt;		&lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;n_var_short&lt;/td&gt;	&lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;h2&gt;Coalesce in a data step&lt;/h2&gt;
&lt;p&gt;
In order to coalesce data in a data step, SAS offers two options:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;a title="Documentation of the coalesce function" href="http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a002518172.htm"&gt;coalesce&lt;/a&gt;(argument-1&amp;lt;..., argument-n&amp;gt;)&lt;/code&gt;. All the arguments need to be numeric. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a title="Documentation of the coalescec function" href="http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a002518268.htm"&gt;coalescec&lt;/a&gt;( argument-1&amp;lt;..., argument-n&amp;gt;)&lt;/code&gt;. It performs a similar functionality for character arguments. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;code&gt;coalescec&lt;/code&gt; in a data-step&lt;/h3&gt;
&lt;p&gt;
It is important to note that if the &lt;code&gt;coalescec&lt;/code&gt; function returns a value to a variable that has not previously been assigned a length, then that variable is given a length of 200 bytes. As a consequence, if one of the arguments has a length above 200 characters, the result may be truncated. To avoid any data truncation, the length of the output variable needs to be set ahead of the function call.
&lt;/p&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;data coalescec_with_data_step;
	set root(drop=n_var:);
&amp;nbsp;
	/*The resulting variable has a length of 200. 
           Note that it has not the same length of the parameters of the function*/
	coalescec_empty_with_c_short = coalescec('', c_var_short);	
&amp;nbsp;
	*the resulting variable is truncated as it has a length of 200 by default;
	coalescec_empty_with_c_long = coalescec('', c_var_long);
&amp;nbsp;
	length coalescec_empty_with_c_long2 $&amp;amp;c_long_var_length;
	coalescec_empty_with_c_long2 = coalescec('', c_var_long);
run;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The resulting dataset has the following structure:
&lt;/p&gt;

&lt;table border="1" cellpadding="3"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Variable&lt;/th&gt;				&lt;th&gt;Type&lt;/th&gt;	&lt;th&gt;Length&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;c_var_long&lt;/td&gt;				&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;300&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;c_var_short&lt;/td&gt;			&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;14&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalescec_empty_with_c_long&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;200&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalescec_empty_with_c_long2&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;300&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalescec_empty_with_c_short&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;200&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
Using the &lt;code&gt;coalescec&lt;/code&gt; function with a parameter of size greater than 200 (here, &lt;code&gt;c_var_long&lt;/code&gt;) will return by default a result with a length of 200. Setting explicitly the size of the output variable through the &lt;code&gt;length&lt;/code&gt; statement is the only way to prevent a possible truncation.
&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;coalesce&lt;/code&gt; in a data-step&lt;/h3&gt;
&lt;p&gt;
The &lt;code&gt;coalesce&lt;/code&gt; function accepts only numerics and returns by default a numeric of length 8, even if the underlying parameters have a shorter length. Unlike its sibling character-based function, there is no risk of truncation as the &lt;a href="http://support.sas.com/documentation/cdl/en/hostwin/63285/HTML/default/viewer.htm#numvar.htm" title="Length and Precision of Variables under Windows"&gt;maximum length&lt;/a&gt; for a numeric in SAS is &lt;em&gt;8&lt;/em&gt;. Specifying the length of the return value in advance allows however the user to have full control of the length of the result.
&lt;/p&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;data coalesce_with_data_step;
	set root(drop=c_var:);
&amp;nbsp;
	*the result has a length of 8 (default);
	coalesce_empty_with_n_short = coalesce('', n_var_short);	
&amp;nbsp;
	coalesce_empty_with_n_long = coalesce('', n_var_long);	
&amp;nbsp;
	*the resulting variable is truncated;
	length coalesce_empty_with_n_long2 3;
	coalesce_empty_with_n_long2 = coalesce('', n_var_long);
run;&lt;/pre&gt;&lt;/div&gt;


&lt;!-- TODO: link to the article related to lost precision --&gt;
&lt;p&gt;
Note that the third variable of the output table (&lt;code&gt;coalesce_empty_with_n_long2&lt;/code&gt;) is not equal anymore to &lt;code&gt;n_var_long&lt;/code&gt; as the numeric has been truncated. Truncating non-integers is not recommended due to the lost of precision.
&lt;/p&gt;

&lt;table border="1" cellpadding="3"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;           &lt;th&gt;Value&lt;/th&gt;       &lt;th&gt;Type&lt;/th&gt;	&lt;th&gt;Length&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_n_short&lt;/td&gt;        &lt;td&gt;10&lt;/td&gt;   &lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_n_long&lt;/td&gt;          &lt;td&gt;10.236455&lt;/td&gt;   &lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_n_long2&lt;/td&gt;        &lt;td&gt;10.236328&lt;/td&gt;   &lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;						
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2&gt;Coalescing in a SQL-Step&lt;/h2&gt;

&lt;h3&gt;&lt;code&gt;coalescec&lt;/code&gt; in SQL&lt;/h3&gt;
&lt;p&gt;
The &lt;code&gt;coalescec&lt;/code&gt; function is still available in the context of a &lt;code&gt;PROC SQL&lt;/code&gt; statement. Similarly to the data step, setting explicitly the length through the column attribute may avoid an undesired truncation.
&lt;/p&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;proc sql;
	create table coalescec_with_sql_step as
	select coalescec('', c_var_short) as coalescec_empty_with_c_short,
			/*the data will be truncated to 200 characters, like in the DATA-step*/
			coalescec('', c_var_long) as coalescec_empty_with_c_long,		
			/*in order to avoid truncation, the length needs to be specified*/	
			coalescec('', c_var_long) as coalescec_empty_with_c_long2 length=&amp;amp;c_long_var_length		
	from root
	;
quit;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The output table is structured as follows:
&lt;/p&gt;
&lt;table border="1" cellpadding="3"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Variable&lt;/th&gt;				&lt;th&gt;Type&lt;/th&gt;	&lt;th&gt;Length&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;coalescec_empty_with_c_long&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;200&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalescec_empty_with_c_long2&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;300&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalescec_empty_with_c_short&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;200&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;h3&gt;&lt;code&gt;coalesce&lt;/code&gt; in SQL&lt;/h3&gt;
&lt;!-- Check the standard --&gt;
&lt;p&gt;
It is recommended to use the &lt;a href="http://support.sas.com/documentation/cdl/en/proc/61895/HTML/default/viewer.htm#a002206368.htm"&gt;&lt;code&gt;coalesce&lt;/code&gt; SQL function&lt;/a&gt; for both numeric and character variables as SAS determines then the type of the output column based on the types of the arguments.  While you need to use two functions, one for each data type, to coalesce variables in a data step, only one function is required in SQL.
&lt;/p&gt;

&lt;p&gt;
Choosing the &lt;code&gt;coalesce&lt;/code&gt; function over the &lt;code&gt;coalescec&lt;/code&gt; function shifts the responsibility of defining the result type to the SQL processor. This behavior is in line with the &lt;a href="http://en.wikipedia.org/wiki/SQL:1999" title="SQL-99 standard"&gt;SQL standard&lt;/a&gt;.
&lt;/p&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;proc sql;
	create table coalesce_with_sql_step as
	select coalesce('', c_var_short) as coalesce_empty_with_c_short,
			coalesce('', c_var_long) as coalesce_empty_with_c_long,
			coalesce('', c_var_short) as coalesce_empty_with_c_short2 length=5,
&amp;nbsp;
			coalesce(., n_var_long) as coalesce_empty_with_n_long,			
			coalesce(., n_var_short) as coalesce_empty_with_n_short,
			coalesce(., n_var_long) as coalesce_empty_with_n_long2 length=3,	
			coalesce(., n_var_short) as coalesce_empty_with_n_short2 length=3
	from root
	;
quit;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
Note that the length of the ouput column is equal to the maximum length of the input parameters.
&lt;/p&gt;

&lt;table border="1" cellpadding="3"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Variable&lt;/th&gt;				&lt;th&gt;Type&lt;/th&gt;	&lt;th&gt;Length&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_c_long&lt;/td&gt;		&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;300&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_c_short&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;14&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_c_short2&lt;/td&gt;	&lt;td&gt;Char&lt;/td&gt;	&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_n_long&lt;/td&gt;		&lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_n_long2&lt;/td&gt;	&lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_n_short&lt;/td&gt;	&lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;coalesce_empty_with_n_short2&lt;/td&gt;	&lt;td&gt;Num&lt;/td&gt;	&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;!-- Add an example where the first parameter is not empty. Validate that the length of the result variable
is the max length of the parameters --&gt;

&lt;h2&gt;Type Conversion&lt;/h2&gt;
&lt;p&gt;
We have covered so far the use of the coalesce functions when all the parameters are of the same type. Let&amp;#8217;s review the behaviours when there is a type mismatch.
&lt;/p&gt;

&lt;h3&gt;Mixing Types in a data-step&lt;/h3&gt;
&lt;p&gt;
In a data-step, the arguments are converted if required. More specifically, if an numeric argument is used with the &lt;code&gt;coalescec&lt;/code&gt; function, SAS will convert it to a character variable. Such a conversion is straightforward and is unlikely to fail. SAS will issue however a note in the log. With the &lt;code&gt;coalesce&lt;/code&gt; function, SAS will try to convert a character variable into a numeric variable. If such a conversion fails, the argument will be set to NULL.
&lt;/p&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;data coalesce_type_issues;
	set root;
&amp;nbsp;
	*SAS is converting the numerical parameter as a string and issue a note;
	coalescec_c_short_with_n_short = coalescec(c_var_short, n_var_short);
&amp;nbsp;
        /*SAS is trying to convert the character parameter as a numerical. 
           The conversion fails, and the converted value is set to null */
	Therefore the returned value is equal to the value of the second parameter;
	coalesce_c_short_with_n_short = coalesce(c_var_short, n_var_short);
run;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Running the previous piece of code will produce the following entry in the log:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column). 89:40
NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column). 92:31
NOTE: Invalid numeric data, c_var='string value', at line 92 column 31.
c_var=string value n_var=10.3
c_long_var=&amp;amp;gt;******************************************************************************************
******************************************************************************************************
******************************************************************************************************
****&amp;amp;lt; coalescec_c_with_n=string value coalesce_c_with_n=10.3
_ERROR_=1 _N_=1&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Mixing types in SQL&lt;/h3&gt;
&lt;p&gt;
While SAS will attempt to convert the parameters to the appropriate types, the &lt;code&gt;coalesce&lt;/code&gt; function generates an error if there is a mismatch.
&lt;/p&gt;

&lt;!--TODO: Fix the compiling error in source file. Is there a conversion error with COALESCEC --&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;proc sql;
	select coalesce(c_var_short, n_var_short) as coalesce_c_with_n	
	from root
	;
&amp;nbsp;
	select coalesce(n_var_short, c_var_short) as coalesce_n_with_c
	from root
	;
&amp;nbsp;
	select coalescec(n_var_short, n_var_short) as coalescec_n_with_n
	from root
	;
quit;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The previous piece of code will issue three consecutive errors of the same type:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;ERROR: The COALESCE function requires its arguments to be of the same data type.&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;
The following table summarizes the differences between &lt;code&gt;coalesce&lt;/code&gt; and &lt;code&gt;coalescec&lt;/code&gt; depending on the context of the processing step. These differences are critical to keep in mind especially when code is being re-factored to use a different processing context. 
&lt;/p&gt;

&lt;!-- check how to merge cells in html table--&gt;
&lt;table border="1" cellpadding="3"&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Context&lt;/th&gt;	&lt;th colspan="2" align="center"&gt;DATA Step&lt;/th&gt;	&lt;th colspan="2" align="center"&gt;SQL Step&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;Function&lt;/th&gt; 	
      &lt;th&gt;&lt;code&gt;coalesce&lt;/code&gt;&lt;/th&gt; 
      &lt;th&gt;&lt;code&gt;coalescec&lt;/code&gt;&lt;/th&gt;
      &lt;th&gt;&lt;code&gt;coalesce&lt;/code&gt;&lt;/th&gt;
      &lt;th&gt;&lt;code&gt;coalescec&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Type of the Parameters&lt;/td&gt;&lt;td&gt;Numeric&lt;/td&gt;&lt;td&gt;Character&lt;/td&gt;&lt;td&gt;Character or Numeric. All the parameters need to be of the same type.&lt;/td&gt;&lt;td&gt;Character&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Result Length&lt;/td&gt;
	&lt;td&gt;8 by default unless specified otherwise&lt;/td&gt;
	&lt;td&gt;200 by default unless specified otherwise&lt;/td&gt;
	&lt;td&gt;The length is adjusted based on the length of the parameters&lt;/td&gt;
	&lt;td&gt;200 by default unless specified otherwise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Risk if length is not specified&lt;/td&gt;
	&lt;td&gt;No loss of precision&lt;/td&gt;
	&lt;td&gt;Possible truncation&lt;/td&gt;
	&lt;td&gt;No loss of precision&lt;/td&gt;
	&lt;td&gt;Possible truncation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Type Conversion&lt;/td&gt;
	&lt;td&gt;Conversion from character to numeric may fail. Generates a note in the log.&lt;/td&gt;
         &lt;td&gt;Automatic conversion. Generates a note in the log.&lt;/td&gt;
	&lt;td&gt;Generates an error if there is an issue with conversion.&lt;/td&gt;
	&lt;td&gt;Automatic conversion. Generates a note in the log.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;!--
TODO: alternatives
link to the source code
--&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;table class="sticky-enabled"&gt;
 &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Attachment&lt;/th&gt;&lt;th&gt;Size&lt;/th&gt; &lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
 &lt;tr class="odd"&gt;&lt;td&gt;&lt;span class="file"&gt;&lt;img class="file-icon" alt="" title="application/pdf" src="/modules/file/icons/application-pdf.png" /&gt; &lt;a href="http://pierrerebours.com/sites/default/files/SAS%20Report.pdf" type="application/pdf; length=168416" title="SAS Report.pdf"&gt;PDF Output&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;164.47 KB&lt;/td&gt; &lt;/tr&gt;
 &lt;tr class="even"&gt;&lt;td&gt;&lt;span class="file"&gt;&lt;img class="file-icon" alt="" title="text/plain" src="/modules/file/icons/text-plain.png" /&gt; &lt;a href="http://pierrerebours.com/sites/default/files/Log.txt" type="text/plain; length=12562" title="Log.txt"&gt;SAS Log&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;12.27 KB&lt;/td&gt; &lt;/tr&gt;
 &lt;tr class="odd"&gt;&lt;td&gt;&lt;span class="file"&gt;&lt;img class="file-icon" alt="" title="application/octet-stream" src="/modules/file/icons/application-octet-stream.png" /&gt; &lt;a href="http://pierrerebours.com/sites/default/files/Program.sas" type="application/octet-stream; length=4092" title="Program.sas"&gt;SAS Program&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;4 KB&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Sun, 12 Feb 2012 07:49:31 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">69 at http://pierrerebours.com</guid>
 <comments>http://pierrerebours.com/blog/coalesce-sas#comments</comments>
  </item>
  <item>
    <title>Slide Number in PowerPoint</title>
    <link>http://pierrerebours.com/blog/slide-number-powerpoint</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/taxonomy/term/139"&gt;Microsoft PowerPoint&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
Recently, I was working on a PowerPoint presentation based on a specific template from a client. As I was about to print the deck, I realized that the slide numbers were missing. As I struggled to figure out how to make the slide number to appear on all the slides, I thought it would be good to share here my experiences. The illustrative screenshots have been taken from PowerPoint 2003. The approach should be similar for more recent versions of PowerPoint.
&lt;/p&gt;
&lt;!--break--&gt;

&lt;h2&gt;Configuring the Master Slides&lt;/h2&gt;
&lt;p&gt;
The first step consists in editing your Master slides. Each presentation can have multiple masters. Usually, the masters come in pair:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;slide master&lt;/em&gt; is the first slide visible from the preview pan.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;title master&lt;/em&gt; is the second slide visible just below the slide master in the preview pan. The title master is optional.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Hovering the mouse indicates the type of the master. Furthermore, the pair is indicated by an icon connecting the two masters.
&lt;/p&gt;

&lt;div class="figure"&gt;
&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/MastersComingInPair.jpg" alt="Masters Coming in Pair" /&gt;
&lt;label&gt;These masters come in pair as indicated by the icon joining the two slides&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
The master slide contains specific areas for the title, the body, the date, the footer, and the slide number. Each of these areas can be moved around. It is always worth checking if all the areas are enabled on the master slide by opening the &lt;em&gt;Master Layout&lt;/em&gt; dialog box. This dialog box contains a list of check boxes, one for each area. When checked, he check boxes are disabled, which is a little bit counter intuitive. To hide an area, you have to select it and then delete it. To make an area visible again, open the "Master Layout" dialog and check the related box which should be now enabled.
&lt;/p&gt;

&lt;table class="figure"&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/MasterLayoutAllChecked.jpg" alt="Master Layout Dialog Box" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/MasterLayoutNoPage.jpg" alt="Master Layout Dialog Box" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;label&gt;The &lt;em&gt;Slide Number&lt;/em&gt; is enabled, and visible on the master&lt;/label&gt;&lt;/td&gt;
&lt;td&gt;&lt;label&gt;The &lt;em&gt;Slide Number&lt;/em&gt; is disabled, and not visible on the master&lt;/label&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;


&lt;p&gt;
It is always good practice to rename the master slide, especially if your PowerPoint file contains many master models. This comes handy to associate a master model to the slides.
&lt;/p&gt;

&lt;div class="figure"&gt;
&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/RenameMasterSlide.jpg" alt="Rename Master Slide Dialog Box" /&gt;
&lt;label&gt;Renaming the Master model&lt;/label&gt;
&lt;/div&gt;

&lt;h2&gt;Configuring the Slides&lt;/h2&gt;
&lt;p&gt;
Once the layout areas have been positioned properly or removed, the slides themselves need to configured. Each slide is associated to a design layout and a text layout. The design layout allows choosing which master to apply to the slide. The text layout determines which member of the master pair will be applied (i.e. the slide master or the title master).
&lt;/p&gt;

&lt;table class="figure"&gt;
&lt;tr&gt;
&lt;td&gt;
	&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/DesignLayout.jpg" alt="Design Layout" /&gt;	
&lt;/td&gt;
&lt;td&gt;
	&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/TextLayout.jpg" alt="Text Layout" /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;label&gt;Design Layout&lt;br/&gt; (CustomMaster1 is selected)&lt;/label&gt;&lt;/td&gt;
&lt;td&gt;	&lt;label&gt;Text Layout &lt;br/&gt;(The title master is selected)&lt;/label&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
 
 &lt;p&gt;
The master contains specific layout areas such as the date or the slide number, these areas need to be activated in the slides. The option is available in the "Header and Footer" dialog, accessible through the menu: "Insert &gt; Slide Number". 
&lt;/p&gt;

&lt;table class="figure"&gt;
&lt;tr&gt;
&lt;td style="padding:10px"&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/SlideNumberMenu.jpg" alt="Menu to access Slide Number" /&gt;&lt;/td&gt;
&lt;td style="padding:10px"&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/SlideNumberDialog.jpg" alt="Slide Number Dialog" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td  colspan="2"&gt;&lt;label&gt;Steps to make the master layout areas appear on the slides&lt;/label&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
 
&lt;p&gt;
As a consequence, the slide number will be displayed if it has been enabled through the "Slide Number" menu &lt;em&gt;and&lt;/em&gt; if the slide number layout area has been made visible in the related master. This dual condition may be a little confusing: the user activates the slide number, but will not see the numbering as it has been disabled in the master.
&lt;/p&gt;
 
&lt;p&gt;
The dialog "Header and Footer" gives however a visual clue using the preview:
&lt;/p&gt;

&lt;table border="1" style="padding: 10px;" &gt;
&lt;tr align="center"&gt;
	&lt;td&gt;&lt;/td&gt;
	&lt;th style="padding: 0.5em"&gt;Slide Number: disabled&lt;/th&gt;
	&lt;th style="padding: 0.5em"&gt;Slide Number: enabled&lt;/th&gt;&lt;/tr&gt;
&lt;tr align="center"&gt;
	&lt;th style="padding: 0.5em"&gt;Slide&lt;br /&gt;Number in Master:&lt;br/&gt; enabled&lt;/th&gt;
	&lt;td&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/SlideNumberDialog_NoNumber_Number.jpg" alt="Layout NoNumber Number" /&gt;&lt;/td&gt;
	&lt;td&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/SlideNumberDialog_Number_Number.jpg" alt="Layout Number Number" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr align="center"&gt;
	&lt;th style="padding: 0.5em"&gt;Slide&lt;br /&gt;Number in Master:&lt;br/&gt; disabled&lt;/th&gt;
	&lt;td&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/SlideNumberDialog_NoNumber_NoNumber.jpg" alt="Layout NoNumber NoNumber"/&gt;&lt;/td&gt;
	&lt;td&gt;&lt;img src="http://pierrerebours.com/sites/default/files/articles/01_PowerPoint/SlideNumberDialog_Number_NoNumber.jpg" alt="Layout Number NoNumber"/&gt;&lt;/td&gt;
&lt;/tr&gt; 
&lt;/table&gt;

&lt;p&gt;
Understanding the factors contributing to the proper display of slide numbers, for example, allows really to understand key concepts related to themes in PowerPoint.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;table class="sticky-enabled"&gt;
 &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Attachment&lt;/th&gt;&lt;th&gt;Size&lt;/th&gt; &lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
 &lt;tr class="odd"&gt;&lt;td&gt;&lt;span class="file"&gt;&lt;img class="file-icon" alt="" title="application/vnd.ms-powerpoint" src="/modules/file/icons/x-office-presentation.png" /&gt; &lt;a href="http://pierrerebours.com/sites/default/files/PresentationTest.ppt" type="application/vnd.ms-powerpoint; length=53248" title="PresentationTest.ppt"&gt;Example of a PowerPoint presentation&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;52 KB&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Sat, 28 Jan 2012 18:18:20 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">68 at http://pierrerebours.com</guid>
 <comments>http://pierrerebours.com/blog/slide-number-powerpoint#comments</comments>
  </item>
  <item>
    <title>Formatting scaled numbers </title>
    <link>http://pierrerebours.com/blog/formatting-scaled-numbers</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/microsoft/net"&gt;.NET&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
Standard formatting in .NET is sometimes not enough to fill specific requirements. For example, when high-level financial reports from big corporations need to be produced, the numbers dealt-with are generally around hundred of millions. Consider the following report where the scale and the currency (M$) is being displayed in the row header.
&lt;/p&gt;
&lt;table border="2"&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;&lt;td&gt;Quarter 1&lt;/td&gt;&lt;td&gt;Quarter 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New York (in M$)&lt;/td&gt;&lt;td&gt;102.76&lt;/td&gt;&lt;td&gt;21.40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Florida (in M$)&lt;/td&gt;&lt;td&gt;32.76&lt;/td&gt;&lt;td&gt;67.40&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
In order to achieve this formatting, a straightforward solution would be to apply a scaling factor to the numbers beforehand.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;string.Format(&amp;quot;{0:N2}&amp;quot;, valueToFormat / 1000000); &lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Sometimes, it is not appropriate nor possible to scale the numbers. In this situation, number scaling using the "," &lt;a href="http://msdn.microsoft.com/en-us/library/0c899ak8.aspx"&gt;custom specifier&lt;/a&gt; could be used. Note the use of two commas since the number to be formatted is divided by 1000 for each comma: 
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;decimal valueToFormat = 1345278000.346M;
string.Format(&amp;quot;0:#,#,,&amp;quot;, valueToFormat ); // displays 1,345 with the invariant culture&lt;/pre&gt;&lt;/div&gt;

&lt;!--break--&gt;
&lt;p&gt;
Most of the examples found in the MSDN fail to explain how to scale the formatted number and keep the decimals at the same time. The trick is to add the "." custom specifier &lt;em&gt;after&lt;/em&gt; the "," comma specifiers:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;decimal valueToFormat = 1345278000.346M;
string.Format(&amp;quot;0:#,#,,.00&amp;quot;, valueToFormat ); // displays 1,345.28 with the invariant culture&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;
This custom formatting technique, however, has some drawbacks:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is harder to read than standard formatting such as &lt;code&gt;{0:N}&lt;/code&gt; or &lt;code&gt;{0:C}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The output may not be consistent with the settings of some cultures. For example, forcing to display two decimal digits may not be compatible with the value of &lt;a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.numberformat.aspx"&gt;&lt;code&gt;CultureInfo.NumberFormat.NumberDecimalDigits&lt;/code&gt;&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Finally, custom specifiers do not mix with the &lt;a href="http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx"&gt;standard numeric specifiers&lt;/a&gt;. The currency symbol cannot be therefore displayed side-by-side with the number. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
A custom formatter called &lt;code&gt;NumberScalingFormatter&lt;/code&gt; has been hence developed to allow scaling the numbers while keeping the underlying settings of the culture. In order to use it, pass the &lt;code&gt;ScalingFactor&lt;/code&gt; and the underlying culture. The following output illustrates the behavior of the custom formatter as well as the custom "," specifier combined with the "." specifier:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;// string.Format(CultureInfo.InvariantCulture,{0:N}, 1345278000.346): 
	1,345,278,000.35
// string.Format(CultureInfo.InvariantCulture,{0:#,#,,}, 1345278000.346): 
	1,345
// string.Format(CultureInfo.InvariantCulture,{0:#,#,,.00}, 1345278000.346): 
	1,345.28
// string.Format(new CultureInfo(&amp;quot;en-US&amp;quot;),{0:#,#,,.00}, 1345278000.346): 
	1,345.28
// string.Format(new CultureInfo(&amp;quot;fr-FR&amp;quot;),{0:#,#,,.00}, 1345278000.346): 
	1 345,28
// string.Format(CultureInfo.InvariantCulture,{0:N}, 1345278000.346): 
	1,345,278,000.35
// string.Format(new NumberScalingFormatter(ScalingFactor.Million, CultureInfo.InvariantCulture),{0:N}, 1345278000.346): 
	1,345.28
// string.Format(new NumberScalingFormatter(ScalingFactor.Million, new CultureInfo(&amp;quot;en-US&amp;quot;)),{0:N}, 1345278000.346): 
	1,345.28
// string.Format(new NumberScalingFormatter(ScalingFactor.Million, new CultureInfo(&amp;quot;fr-FR&amp;quot;)),{0:N}, 1345278000.346): 
	1 345,28&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
 For an introduction to custom formatter, please check out the &lt;a href="http://codebetter.com/blogs/david.hayden/archive/2006/03/12/140732.aspx"&gt;post&lt;/a&gt; from David Hayden.  A basic outline of the code follows. 
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;public enum ScalingFactor
{
    None,
    Million,
    Billion
}
&amp;nbsp;
public class NumberScalingFormatter : IFormatProvider, ICustomFormatter
{
    private readonly CultureInfo _underlyingCulture;
    private readonly ScalingFactor _scalingFactor;
&amp;nbsp;
&amp;nbsp;
    public NumberScalingFormatter(ScalingFactor scalingFactor, CultureInfo underlyingCulture)
    {
        if (underlyingCulture == null)
        {
            throw new ArgumentNullException();
        }
        _scalingFactor = scalingFactor;
        _underlyingCulture = underlyingCulture;
    }
&amp;nbsp;
    public ScalingFactor Factor
    {
        get
        {
            return _scalingFactor;
        }
    }
&amp;nbsp;
    public CultureInfo Culture
    {
        get
        {
            return _underlyingCulture;
        }
    }
&amp;nbsp;
&amp;nbsp;
    #region IFormatProvider Members
&amp;nbsp;
    public object GetFormat(Type formatType)
    {
        object formatter = null;
        if (formatType == typeof(ICustomFormatter))
        {
            formatter = this;
        }
        else
        {
            formatter = _underlyingCulture.GetFormat(formatType);
        }
        return formatter;
    }
&amp;nbsp;
    #endregion
&amp;nbsp;
    #region ICustomFormatter Members
    private int GetUnderlyingThousandScalingFactor()
    {
        int underlyingThousandScalingFactor;
&amp;nbsp;
        switch (_scalingFactor)
        {
            case ScalingFactor.None:
                underlyingThousandScalingFactor = 0;
                break;
&amp;nbsp;
            case ScalingFactor.Billion:
                underlyingThousandScalingFactor = 3;
                break;
&amp;nbsp;
            default:
            case ScalingFactor.Million:
                underlyingThousandScalingFactor = 2;
                break;
        }
        return underlyingThousandScalingFactor;
    }
&amp;nbsp;
    private object Scale(object arg)
    {
        object scaledValue = null;
&amp;nbsp;
        if (arg == null)
        {
            scaledValue = null;
        }
        else if (_scalingFactor == ScalingFactor.None)
        {
            scaledValue = arg;
        }
        else
        {
            int underlyingThousandScalingFactor = GetUnderlyingThousandScalingFactor();
            try
            {
                double convertedValue = Convert.ToDouble(arg);
                scaledValue = Math.Pow(10, underlyingThousandScalingFactor * -3) * convertedValue;
            }
            catch (InvalidCastException)
            {
&amp;nbsp;
            }
        }
        return scaledValue;
    }
&amp;nbsp;
    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        StringBuilder formattableString = new StringBuilder(&amp;quot;{0&amp;quot;);
        if (!string.IsNullOrEmpty(format))
        {
            formattableString.Append(&amp;quot;:&amp;quot;);
            formattableString.Append(format);
        }
        formattableString.Append(&amp;quot;}&amp;quot;);
&amp;nbsp;
        return string.Format(_underlyingCulture, formattableString.ToString(), Scale(arg));
    }
&amp;nbsp;
    #endregion
}&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
&lt;a name="download"&gt;
&lt;img class="floating-image" height="24" width="24" alt="Download icon" src="http://farm4.static.flickr.com/3161/2799685860_b9f2d9e1ed_o.png"/&gt;
&lt;/a&gt;
The source code as well as the &lt;a href="http://www.nunit.org"&gt;NUnit&lt;/a&gt; test cases are available from the SVN &lt;a href="https://pierrerebours.devguard.com/svn/default/dotnet/lab/StringFormatting/"&gt;directory&lt;/a&gt;. Please refer to the &lt;a href="http://pierrerebours.com/subversion-instructions"&gt;instruction&lt;/a&gt; to download the tarballs. 
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Sun, 10 Jan 2010 19:28:44 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">67 at http://pierrerebours.com</guid>
 <comments>http://pierrerebours.com/blog/formatting-scaled-numbers#comments</comments>
  </item>
  <item>
    <title>MWSnap Review</title>
    <link>http://pierrerebours.com/blog/mwsnap-review</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/screenshot"&gt;Screenshot&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-taxonomy-vocabulary-5 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Stories:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/stories/review"&gt;Review&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
&lt;a href="http://www.mirekw.com/winfreeware/mwsnap.html" title="MWSnap" class="floating-image"&gt;
  &lt;img src="http://farm4.static.flickr.com/3094/3172582499_4867cbd238_o.jpg" width="53" height="58" alt="MWSnap Icon" /&gt;
&lt;/a&gt;
When it comes to create screenshots, I often use &lt;a href="http://www.mirekw.com/winfreeware/mwsnap.html" title="Site of MWSnap"&gt;MWSnap&lt;/a&gt;, a freeware written by &lt;a href="http://www.mirekw.com" title="Website of Mirek Wojtowicz"&gt;Mirek Wojtowicz&lt;/a&gt;.
This tool offers all the core functionalities one may expect from a screenshot application. 
MWSnap was recommended to me by &lt;a href="http://www.mike95.com" title="Website of Michael Olivero"&gt;Michael Olivero&lt;/a&gt;.
&lt;/p&gt;

&lt;div class="figure"&gt;
  &lt;a href="http://www.flickr.com/photos/pierrer/3172564383/" title="MWSnap"&gt;
   &lt;img src="http://farm4.static.flickr.com/3256/3172564383_c3506bcbba_m.jpg" width="240" height="180" alt="MWSnap" /&gt;&lt;/a&gt;
  &lt;label&gt;MWSnap start page&lt;/label&gt;
&lt;/div&gt;

&lt;!--break--&gt;

&lt;p&gt;
The tool allows snapping variable rectangle areas as well as entire windows and menus. The snapped images can then be saved as &lt;a href="http://en.wikipedia.org/wiki/JPEG" title="JPEG format"&gt;jpeg&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/Portable_Network_Graphics" title="PNG format"&gt;png&lt;/a&gt;. The ability to edit the snapshot by adding &lt;em&gt;cursors&lt;/em&gt; is handy to document user interaction. Finally, the &lt;em&gt;auto-saving&lt;/em&gt; functionality with auto-generated file names will increase productivity for high-volume scenarios.
&lt;/p&gt;

&lt;div class="figure"&gt;
  &lt;table style="width: 90%"&gt;
    &lt;tr&gt;
    &lt;td&gt;
      &lt;a href="http://www.flickr.com/photos/pierrer/3172564381/" title="MWSnap Cursors"&gt;
          &lt;img src="http://farm2.static.flickr.com/1159/3172564381_9309b48752_m.jpg" width="65" height="240" alt="MWSnap Cursors" /&gt;
       &lt;/a&gt;
       &lt;label&gt;Cursors&lt;/label&gt;
    &lt;/td&gt;
    &lt;td&gt;
        &lt;a href="http://www.flickr.com/photos/pierrer/3172564377/" title="MWSnap AutoSaving"&gt;
            &lt;img src="http://farm2.static.flickr.com/1148/3172564377_e9c0dba39a_m.jpg" width="240" height="170" alt="MWSnap AutoSaving" /&gt;
         &lt;/a&gt;
        &lt;label&gt;Auto-Saving&lt;/label&gt;
     &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;

&lt;/div&gt;

&lt;p&gt;
MWSnap has been released before the advent of &lt;a href="http://en.wikipedia.org/wiki/Windows_Vista" title="Windows Vista"&gt;Vista&lt;/a&gt;. Under Vista, most of the functionalities of MWSnap work, but some glitches are expected when snapping windows and menus.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Tue, 06 Jan 2009 06:30:51 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">64 at http://pierrerebours.com</guid>
  </item>
  <item>
    <title>Order returned by GetMethods</title>
    <link>http://pierrerebours.com/blog/order-returned-getmethods</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/microsoft/net/csharp"&gt;C#&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/microsoft/net"&gt;.NET&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/clr"&gt;CLR&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/reflection"&gt;Reflection&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
When calling the &lt;a href="http://msdn.microsoft.com/en-us/library/4d848zkb.aspx"&gt;&lt;code&gt;GetMethods&lt;/code&gt;&lt;/a&gt; function which lists the methods for a given type, we should keep in mind that this function does not return methods in a particular order. 
More specifically, the methods are not necessarily in the same order it has been &lt;em&gt;declared&lt;/em&gt; in the source code. 
This discrepancy is due to some caching performed by the .NET Framework for &lt;a href="http://msdn.microsoft.com/en-gb/magazine/cc163759.aspx" title="Performance with Reflection"&gt;better performance&lt;/a&gt; as explained in a &lt;a href="http://blogs.msdn.com/haibo_luo/archive/2006/07/09/661091.aspx" title="Member Order Returned by GetFields, GetMethods..."&gt;post&lt;/a&gt; by Haibo Luo.
This article is aimed at outlining solutions to order the methods returned by &lt;code&gt;GetMethods&lt;/code&gt; in the declaring order.
&lt;/p&gt;

&lt;!--break--&gt;

&lt;h2&gt;Returned Index vs. Ordered Index&lt;/h2&gt;
&lt;p&gt;
Even when reflection operations are executed on a CLR type for the first time, i.e., when the cache is empty, the order returned by &lt;code&gt;GetMethods&lt;/code&gt; may not be the same as the declaration order. In the following example, a class with 200 randomly generated methods has been compiled. Each method has the same signature:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;public class Test {
  public decimal AJODCUJQ(int parameter) {
    throw new NotImplementedException();
  }
&amp;nbsp;
 // 199 other methods with the same signature follow
}&lt;/pre&gt;&lt;/div&gt;

&lt;div class="figure"&gt;
&lt;a href="http://www.flickr.com/photos/pierrer/3146696197/" title="View of the class using Reflector"&gt;&lt;img src="http://farm4.static.flickr.com/3286/3146696197_19abe43a54_m.jpg" width="208" height="240" alt="Reflector screenshot" /&gt;&lt;/a&gt;
&lt;label&gt;View of the class using Reflector&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
The following call to &lt;code&gt;GetMethods&lt;/code&gt; returns 200 &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.aspx" title="Documentation for MethodInfo"&gt;&lt;code&gt;MethodInfo&lt;/code&gt;&lt;/a&gt; instances.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;typeof(Test).GetMethods(BindingFlags.Instance | 
                                         BindingFlags.Static | 
                                         BindingFlags.Public | 
                                         BindingFlags.DeclaredOnly);&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
 The returned order is however different than the declared order. The first declared function (index #0) is returned as the 116th method. Several cut-offs points are visible: methods #170 to #199 are the first returned, followed by methods #85 to #169, then by methods #0 to 84. Such behaviors may not be noticeable for types having a smaller numbers of methods. 
&lt;/p&gt;

&lt;div class="figure"&gt;
&lt;a href="http://www.flickr.com/photos/pierrer/3146594451/" title="Returned Index vs. Declared Indexes"&gt;
&lt;img src="http://farm4.static.flickr.com/3243/3146594451_ec58be0a66.jpg" width="500" height="307" alt="Graph of returned index vs. declared index" /&gt;&lt;/a&gt;
&lt;label&gt;Returned Index vs. Declared Indexes (see &lt;a href="#attachments"&gt;data file&lt;/a&gt;)&lt;/label&gt;
&lt;/div&gt;

&lt;h2&gt;Solutions&lt;/h2&gt;
&lt;p&gt;
Code using &lt;code&gt;GetMethods&lt;/code&gt; cannot depend on the order in which methods are returned, because that order &lt;em&gt;varies&lt;/em&gt;.
Several strategies could be implemented to order the methods in the declaring order, i.e., the &lt;em&gt;x&lt;/em&gt;th method declared in the original source code will be the &lt;em&gt;x&lt;/em&gt;th method being returned.
&lt;/p&gt;

&lt;h3&gt;&lt;a name="metadata-token"&gt;MetaData Token&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;
The first solution could use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.memberinfo.metadatatoken.aspx"&gt;&lt;code&gt;MetaDataToken&lt;/code&gt;&lt;/a&gt; property of &lt;code&gt;MethodInfo&lt;/code&gt;.
A &lt;a href="http://msdn.microsoft.com/en-us/library/ms404456.aspx" title="Metadata Tokens Overview"&gt;metadata token&lt;/a&gt; is used to locate the record that contains the metadata for an entity such as a type, a method, or a field. The metadata engine uses the token to index into a specific metadata table in a given metadata scope.
By experience, we can observe a direct correlation between the value of the metadata token and the declared index of the related method. I have not found, however, the confirmation of such a behavior in the documentation and I cannot therefore advice to use this trick for production systems. 
&lt;/p&gt;

&lt;h3&gt;&lt;a name="automation"&gt;Visual Studio Automation&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;
If the developed application can run in the context of Visual Studio, using &lt;a href="http://msdn.microsoft.com/en-us/library/xc52cke4(VS.80).aspx"&gt;Visual Studio Automation&lt;/a&gt; offers a rich alternative to reflection.
Using this framework is, however, outside the scope of this article.
&lt;/p&gt;

&lt;h3&gt;ICorDebug&lt;/h3&gt;
&lt;p&gt;
&lt;a href="http://blogs.msdn.com/jmstall/archive/2004/10/05/237954.aspx"&gt;&lt;em&gt;ICorDebug&lt;/em&gt;&lt;/a&gt; is a managed debugging public API.
&lt;a href="http://blogs.msdn.com/jmstall/archive/2005/11/08/mdbg_linkfest.aspx"&gt;&lt;em&gt;MDbg&lt;/em&gt;&lt;/a&gt;, which can be &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=38449a42-6b7a-4e28-80ce-c55645ab1310"&gt;downloaded&lt;/a&gt; from the Microsoft site, simplifies the functionalities by wrapping ICorDebug in a much simplier object model.
Mike Stall provides an &lt;a href="http://blogs.msdn.com/jmstall/articles/sample_pdb2xml.aspx"&gt;example&lt;/a&gt; which loads a &lt;a href="http://en.wikipedia.org/wiki/Program_database" title="Program Database File"&gt;pdb file&lt;/a&gt; and outputs the symbols as a XML file. 
In this example, it is shown how the MDbg API can extract the line numbers where the method has been declared.
By using the information provided by &lt;em&gt;MDbg&lt;/em&gt;, the methods returned by &lt;code&gt;GetMethods&lt;/code&gt; can be sorted in the declaring order.
&lt;/p&gt;

&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;
The implementation relies on a core of services defined as interfaces:
&lt;/p&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;public interface IMethodProvider
{
    MethodInfo[] GetMethods(Type type);
}
public interface IMethodFilter
{
   bool IsMatch(MethodInfo methodInfo);
   void Initialize();
}
public interface ILineNumberProvider
{
   int GetStartLineNumber(MethodInfo method);
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The service which returns an array of methods is called &lt;code&gt;IMethodProvider&lt;/code&gt;. A simple implementation of this service is done by &lt;code&gt;PublicReflectionMethodProvider&lt;/code&gt; which directly calls &lt;code&gt;GetMethods&lt;/code&gt;. This implementation, as we have seen it previously, does not guaranty that the methods will be sorted in the same order as they have been declared. &lt;code&gt;OrderedMethodProvider&lt;/code&gt; implements also &lt;code&gt;IMethodProvider&lt;/code&gt; but returns ordered methods thanks to the help of an inner service &lt;code&gt;ILineNumberProvider&lt;/code&gt;. 
&lt;code&gt;ILineNumberProvider&lt;/code&gt; is implemented by &lt;code&gt;MDbgLineNumberProvider&lt;/code&gt; which extracts the line number by using the MDbg library.
If the pdb file related to the &lt;code&gt;MethodInfo&lt;/code&gt; does not exist, a &lt;code&gt;FileNotFoundException&lt;/code&gt; is thrown.
Note that other implementations could use the &lt;a href="#metadata-token"&gt;metadata token&lt;/a&gt; or &lt;a href="#automation"&gt;Visual Studio Automation&lt;/a&gt;.
&lt;/p&gt;

&lt;div class="figure"&gt;
&lt;a href="http://www.flickr.com/photos/pierrer/3146977005/" title="Class Diagram"&gt;&lt;img src="http://farm4.static.flickr.com/3220/3146977005_5c5bcc2122.jpg" width="500" height="370" alt="Class Diagram" /&gt;&lt;/a&gt;
&lt;label&gt;Class Diagram&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a name="download"&gt;
&lt;img class="floating-image" height="24" width="24" alt="Download icon" src="http://farm4.static.flickr.com/3161/2799685860_b9f2d9e1ed_o.png"/&gt;
&lt;/a&gt;
The source code as well as the &lt;a href="http://www.nunit.org"&gt;NUnit&lt;/a&gt; test cases are available from the SVN &lt;a href="https://pierrerebours.devguard.com/svn/default/dotnet/lab/MethodOrdering/"&gt;directory&lt;/a&gt;. Please refer to the &lt;a href="http://pierrerebours.com/subversion-instructions"&gt;instruction&lt;/a&gt; to download the tarballs. 
&lt;/p&gt;

&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;table class="sticky-enabled"&gt;
 &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Attachment&lt;/th&gt;&lt;th&gt;Size&lt;/th&gt; &lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
 &lt;tr class="odd"&gt;&lt;td&gt;&lt;span class="file"&gt;&lt;img class="file-icon" alt="" title="text/csv" src="/modules/file/icons/text-x-generic.png" /&gt; &lt;a href="http://pierrerebours.com/sites/default/files/DataGetMethods.csv" type="text/csv; length=2323" title="DataGetMethods.csv"&gt;Returned vs. Declared Ordering (CSV file)&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;2.27 KB&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Mon, 29 Dec 2008 16:15:42 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">63 at http://pierrerebours.com</guid>
  </item>
  <item>
    <title>CanShrink and CanGrow Behaviors</title>
    <link>http://pierrerebours.com/blog/canshrink-and-cangrow-behaviors</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/microsoft/sql-server/ssrs"&gt;SSRS&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/ssrs-2005"&gt;SSRS 2005&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
In Reporting Services (&lt;a href="http://en.wikipedia.org/wiki/SQL_Server_Reporting_Services" title="SQL Server Reporting Services"&gt;SSRS&lt;/a&gt;), the &lt;code&gt;CanGrow&lt;/code&gt; property indicates whether the size of the text box can increase &lt;em&gt;vertically&lt;/em&gt; according to its content.
Similarly, &lt;code&gt;CanShrink&lt;/code&gt; decreases the &lt;em&gt;height&lt;/em&gt; of the text box according to its content. 
Controlling dynamically the height of report elements is only possible through these properties since the &lt;code&gt;Height&lt;/code&gt; property &lt;a href="http://social.msdn.microsoft.com/forums/en-US/sqlreportingservices/thread/9e6043f1-c458-4540-be59-d37b02feab8a/" title="Expression on the Width property not yet implemented in SSRS 2008"&gt;cannot be bound&lt;/a&gt; to an expression.
These two properties are therefore useful to create reports which can be scaled to both small and large contents. 
Unfortunately, &lt;code&gt;CanGrow&lt;/code&gt; and &lt;code&gt;CanShrink&lt;/code&gt; behave differently for each &lt;a href="http://msdn.microsoft.com/en-us/library/cc627537.aspx" title="Available rendering extensions with SSRS"&gt;rendering extension&lt;/a&gt;.
&lt;/p&gt;
&lt;!--break--&gt;
&lt;div class="figure"&gt;
&lt;a href="http://www.flickr.com/photos/pierrer/3129369776/" title="Design Surface"&gt;&lt;img src="http://farm4.static.flickr.com/3111/3129369776_df896b4dc1.jpg" width="244" height="500" alt="Design Surface" /&gt;&lt;/a&gt;
&lt;label&gt;Report testing the behaviors of &lt;code&gt;CanGrow&lt;/code&gt; and &lt;code&gt;CanShrink&lt;/code&gt;&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
Let's demonstrate such behaviors with a &lt;a href="#attachments"&gt;report&lt;/a&gt; created with SSRS 2005. 
The following elements have been created without any padding:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;A &lt;span  style="color: LimeGreen"&gt;text box&lt;/span&gt; with a non-empty value (&lt;code&gt;Value = "Content"&lt;/code&gt;) and &lt;code&gt;CanShrink&lt;/code&gt; set to true.&lt;/li&gt;
 &lt;li&gt;A &lt;span style="color: CornflowerBlue"&gt;text box&lt;/span&gt; with a non-empty value (&lt;code&gt;Value = "Content"&lt;/code&gt;) and &lt;code&gt;CanGrow&lt;/code&gt; set to true. &lt;/li&gt;
 &lt;li&gt;A &lt;span style="color: Peru"&gt;text box&lt;/span&gt; with a non-empty value (&lt;code&gt;Value = "Content"&lt;/code&gt;) where &lt;code&gt;CanShrink&lt;/code&gt; and &lt;code&gt;CanGrow&lt;/code&gt; are both set to true.&lt;/li&gt;
 &lt;li&gt;A &lt;span style="color: Magenta"&gt;text box&lt;/span&gt; with an empty value and &lt;code&gt;CanShrink&lt;/code&gt; set to true.&lt;/li&gt;
 &lt;li&gt;A &lt;span style="color: LightSteelBlue"&gt;text box&lt;/span&gt; with a single space as value (&lt;code&gt;Value = " "&lt;/code&gt;) where &lt;code&gt;CanShrink&lt;/code&gt; is set to true.&lt;/li&gt;
 &lt;li&gt;A non-visible &lt;span style="color: Orange"&gt; text box&lt;/span&gt; (&lt;code&gt;Visibility.Hidden = true&lt;/code&gt;).&lt;/li&gt;
 &lt;li&gt;A non-visible &lt;span style="color: PaleTurquoise"&gt;text box&lt;/span&gt; where &lt;code&gt;CanShrink&lt;/code&gt; is set to true.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="figure"&gt;
&lt;a href="http://www.flickr.com/photos/pierrer/3127230413/" title="Font Property"&gt;
   &lt;img src="http://farm4.static.flickr.com/3204/3127230413_c830d7ceb0_o.jpg" width="394" height="87" alt="Font Property " /&gt;
&lt;/a&gt;
&lt;label&gt;The &lt;code&gt;FontSize&lt;/code&gt; can be changed using a report parameter&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
The &lt;code&gt;FontSize&lt;/code&gt; property of each text box is bound to &lt;code&gt;FontSize&lt;/code&gt; report parameter (&lt;code&gt;= Parameters!FontSize.Value&lt;/code&gt;). The available values are 6pt, 10pt, 16pt, and 30pt.
&lt;/p&gt;

&lt;h2&gt;Rendering Extensions&lt;/h2&gt;
&lt;p&gt;
First, let's have a look on how the report is rendered with IE 7.
&lt;/p&gt;

&lt;div class="figure"&gt;
&lt;table&gt;
&lt;tr&gt;
  &lt;td  valign="top"&gt;
    &lt;a href="http://www.flickr.com/photos/pierrer/3128540165/" title="IE7 6pt"&gt;&lt;img src="http://farm4.static.flickr.com/3256/3128540165_3c5925118c_m.jpg" width="125" height="240" alt="IE7 6pt" /&gt;
   &lt;/a&gt;
   &lt;label&gt;6pt&lt;/label&gt;
  &lt;/td&gt;
  &lt;td  valign="top"&gt;
    &lt;a href="http://www.flickr.com/photos/pierrer/3128539859/" title="IE7 10pt"&gt;&lt;img src="http://farm4.static.flickr.com/3221/3128539859_77849c15af_m.jpg" width="125" height="240" alt="IE7 10pt" /&gt;&lt;/a&gt;
   &lt;label&gt;10pt&lt;/label&gt;
  &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td  valign="top"&gt;
     &lt;a href="http://www.flickr.com/photos/pierrer/3128539909/" title="IE7 16pt"&gt;&lt;img src="http://farm4.static.flickr.com/3206/3128539909_d41f267e96_m.jpg" width="123" height="240" alt="IE7 16pt" /&gt;&lt;/a&gt;
    &lt;label&gt;16pt&lt;/label&gt;
   &lt;/td&gt;
   &lt;td  valign="top"&gt;
    &lt;a href="http://www.flickr.com/photos/pierrer/3128539987/" title="IE7 30pt"&gt;&lt;img src="http://farm4.static.flickr.com/3247/3128539987_3928afbb18_m.jpg" width="102" height="240" alt="IE7 30pt" /&gt;&lt;/a&gt;
    &lt;label&gt;30pt&lt;/label&gt;
   &lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;label&gt;Rendering with IE 7&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;code&gt;CanGrow&lt;/code&gt; and &lt;code&gt;CanShrink&lt;/code&gt; behave as expected for all the text boxes having a non-empty &lt;code&gt;Value&lt;/code&gt;. The shrinkable &lt;span  style="color: LimeGreen"&gt;text box&lt;/span&gt; cuts off content too big for the specified height. 
Similarly, the &lt;span style="color: CornflowerBlue"&gt;text box&lt;/span&gt; which can only grow has its height unchanged when the FontSize is equal to 10pt.
Notice that the &lt;span style="color: Magenta"&gt;text box&lt;/span&gt;, which can shrink but has no value, does not have its height changed. The &lt;code&gt;Value&lt;/code&gt; property needs to have a space to have its height resized to zero.
&lt;/p&gt;

&lt;div class="figure"&gt;
&lt;a href="http://www.flickr.com/photos/pierrer/3129370024/" title="PDF 10pt"&gt;&lt;img src="http://farm4.static.flickr.com/3080/3129370024_a395f5e33a_m.jpg" width="122" height="240" alt="PDF 10pt" /&gt;&lt;/a&gt;
&lt;label&gt;Rendering with PDF&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
The PDF rendering is the most accurate. Similarly to the HTML rendering, the &lt;code&gt;CanGrow&lt;/code&gt; and &lt;code&gt;CanShrink&lt;/code&gt; modify the heights of the text boxes as expected. Furthermore, the &lt;span style="color: Magenta"&gt;text box&lt;/span&gt; with an empty &lt;code&gt;Value&lt;/code&gt; has been removed from the flow of the document. On the other hand, the hidden text boxes continue to occupy some real-estate on the report.
Combining the &lt;code&gt;CanShrink&lt;/code&gt; property with just a space for the &lt;code&gt;Value&lt;/code&gt; property does not, however, hide the text box contrarily to the HTML rendering.
&lt;/p&gt;

&lt;div class="figure"&gt;
&lt;a href="http://www.flickr.com/photos/pierrer/3128540113/" title="Excel 10pt"&gt;&lt;img src="http://farm4.static.flickr.com/3228/3128540113_510bcdff70_m.jpg" width="121" height="240" alt="Excel 10pt" /&gt;&lt;/a&gt;
&lt;label&gt;Rendering with Excel&lt;/label&gt;
&lt;/div&gt;

&lt;p&gt;
Finally, it is obvious with the Excel rendering that the &lt;code&gt;CanGrow&lt;/code&gt; and &lt;code&gt;CanShrink&lt;/code&gt; properties fail to adjust the height of the Excel rows. It is a frustrating limitation of the Excel rendering.
&lt;/p&gt;

&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;
When using &lt;code&gt;CanGrow&lt;/code&gt; and &lt;code&gt;CanShrink&lt;/code&gt;, be aware what their behaviors can change depending on the rendering extension being used:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CanShrink&lt;/code&gt; will remove the text box from the &lt;a href="http://stackoverflow.com/questions/263909/how-to-shrink-list-object-in-reporting-services"&gt;document flow&lt;/a&gt; for only specific rendering format.&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;Value&lt;/code&gt; property may cause &lt;a href="http://stackoverflow.com/questions/126382/define-small-row-height-in-reporting-services-2005"&gt;some issues&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Visibility&lt;/code&gt; property seems to override the intended behavior of &lt;code&gt;CanShrink &lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sqlblogcasts.com/blogs/jorg/archive/2007/11/19/SSRS-_1320_-invalid-row-heights.aspx" title="Invalid row height"&gt;Padding&lt;/a&gt; needs to be set to zero to fully hide a shrinkable element.&lt;/li&gt;
&lt;/ul&gt;






&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;table class="sticky-enabled"&gt;
 &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Attachment&lt;/th&gt;&lt;th&gt;Size&lt;/th&gt; &lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
 &lt;tr class="odd"&gt;&lt;td&gt;&lt;span class="file"&gt;&lt;img class="file-icon" alt="" title="application/octet-stream" src="/modules/file/icons/application-octet-stream.png" /&gt; &lt;a href="http://pierrerebours.com/sites/default/files/CanShrink.rdl" type="application/octet-stream; length=8987" title="CanShrink.rdl"&gt;Report testing CanGrow and CanShrink&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;8.78 KB&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Mon, 22 Dec 2008 11:09:38 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">62 at http://pierrerebours.com</guid>
 <comments>http://pierrerebours.com/blog/canshrink-and-cangrow-behaviors#comments</comments>
  </item>
  <item>
    <title>Load Testing using The Grinder</title>
    <link>http://pierrerebours.com/blog/load-testing-using-grinder</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/microsoft/net/aspnet"&gt;ASP.NET&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/taxonomy/term/30"&gt;Java&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/load-testing"&gt;Load-Testing&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/performance"&gt;Performance&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
Performing preliminary load testing on web applications does not require the use of complex tools such as &lt;a href="https://h10078.www1.hp.com/cda/hpms/display/main/hpms_content.jsp?zn=bto&amp;amp;cp=1-11-15-17^8_4000_100__" title="Load Runner from HP"&gt;Load Runner&lt;/a&gt;.
An open-source tool called &lt;a href="http://grinder.sourceforge.net/" title="Open-Source load testing tool"&gt;The Grinder&lt;/a&gt; provides a simple way for developers to perform load testing before handing out the application to &lt;a href="http://en.wikipedia.org/wiki/Quality_Assurance" title="What is Quality Insurance (QA)?"&gt;Quality Assurance&lt;/a&gt;.
With &lt;em&gt;The Grinder&lt;/em&gt;, the load tests are defined using &lt;a href="http://www.jython.org/Project" title="Python running on Java"&gt;Jython&lt;/a&gt; scripts, and then are run by &lt;em&gt;agents&lt;/em&gt; which could be distributed over the network. A &lt;em&gt;property file&lt;/em&gt; defines which load tests should be run, how many times, and on how many threads. A central application referred to as the &lt;em&gt;console&lt;/em&gt; starts the agents, collects the responses, and monitors the number of requests per second (&lt;a href="http://en.wikipedia.org/wiki/Requests_per_second" title="What is RPS?"&gt;RPS&lt;/a&gt;). The authors of this tool provide a short but useful &lt;a href="http://grinder.sourceforge.net/g3/getting-started.html"&gt;overview&lt;/a&gt; of the architecture.
&lt;/p&gt;

&lt;p&gt;
Installing &lt;em&gt;The Grinder&lt;/em&gt; is a matter of unzipping the archive since the tool is written in Java. However, making the tool work as indented requires to dig into the documentation a little bit.
This article is intended to assist people interested in getting up and running the tool on a Widows environment as quickly as possible.
&lt;/p&gt;

&lt;!--break--&gt;

&lt;p&gt;
&lt;a name="download"&gt;
&lt;img class="floating-image" height="24" width="24" alt="Download icon" src="http://farm4.static.flickr.com/3161/2799685860_b9f2d9e1ed_o.png"/&gt;
&lt;/a&gt;
The companion files are available from the SVN &lt;a href="https://pierrerebours.devguard.com/svn/default/dotnet/lab/GrinderSettings/"&gt;directory&lt;/a&gt;. Please refer to the &lt;a href="http://pierrerebours.com/subversion-instructions"&gt;instruction&lt;/a&gt; to download the tarballs. 
&lt;/p&gt;

&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;
On my desktop, I have created a folder called &lt;code&gt;grinder&lt;/code&gt;. The archive downloaded from &lt;a href="http://sourceforge.net/projects/grinder" title="Download the Grinder"&gt;Sourceforge&lt;/a&gt; was extracted in this folder as &lt;code&gt;grinder-3.1&lt;/code&gt;.
A couple of batch files will need to be created to conveniently start up the agents and the console.
The first batch file &lt;code&gt;setGrinderEnv.bat&lt;/code&gt; defines environment variables which will be reused:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;set GRINDERPATH=&amp;quot;C:\Documents and Settings\pierre rebours\Desktop\grinder\grinder-3.1&amp;quot;
set GRINDERPROPERTIES=&amp;quot;C:\Documents and Settings\pierre rebours\Desktop\grinder\grinder.properties&amp;quot;
set CLASSPATH=%GRINDERPATH%\lib\grinder.jar;%CLASSPATH%&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Since &lt;em&gt;The Grinder&lt;/em&gt; is a Java-based tool, the infamous environment variable &lt;code&gt;CLASS_PATH&lt;/code&gt; needs to be defined.
The environment variable &lt;code&gt;GRINDERPROPERTIES&lt;/code&gt; refers to the path of the property file. More about this file in a moment.
&lt;/p&gt;

&lt;p&gt;
Starting the console  is done using &lt;code&gt;startConsole.bat&lt;/code&gt;:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;call &amp;quot;C:\Documents and Settings\pierre rebours\Desktop\grinder\setGrinderEnv.cmd&amp;quot;
java -cp %CLASSPATH% net.grinder.Console &lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Similarly, &lt;code&gt;startAgent.bat&lt;/code&gt; starts the agent(s) 
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;call &amp;quot;C:\Documents and Settings\pierre rebours\Desktop\grinder\setGrinderEnv.cmd&amp;quot;
java -cp %CLASSPATH% net.grinder.Grinder %GRINDERPROPERTIES%&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Property File&lt;/h2&gt;
&lt;p&gt;
The load test is defined using the property file. The configuration entry &lt;code&gt;grinder.script = http.py&lt;/code&gt; indicates the path of the Jython script which will be run. Other interesting configurations include the number of processes created by each agent (&lt;code&gt;grinder.processes&lt;/code&gt;) and the number of threads for each process (&lt;code&gt;grinder.threads&lt;/code&gt;).
&lt;/p&gt;
&lt;p&gt;
I would also recommend to explicitly specify the log and the temporary directories:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="python geshifilter-python" style="font-family:monospace;"&gt;# The directory in which worker process logs should be created. 
grinder.logDirectory = log
&amp;nbsp;
# Additional arguments to worker process JVMs.
grinder.jvm.arguments = -Dpython.cachedir=&amp;quot;C:\\Documents and Settings\\pierre rebours\\Desktop\\grinder\\tmp&amp;quot;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Load Test Specification&lt;/h2&gt;
&lt;p&gt;
Simulating a request to a web server could be defined as follows:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="python geshifilter-python" style="font-family:monospace;"&gt;from net.grinder.script import Test
from net.grinder.script.Grinder import grinder
from net.grinder.plugin.http import HTTPPluginControl, HTTPRequest
from HTTPClient import NVPair
&amp;nbsp;
test1 = Test(1, &amp;quot;WebService&amp;quot;)
request1 = test1.wrap(HTTPRequest())
&amp;nbsp;
class TestRunner:
	def __call__(self):		
		request1.GET(&amp;quot;http://localhost/MyApplication/PresentationService.ashx&amp;quot;)&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
A custom proxy server can also be defined. In the following case, the proxy is defined as &lt;em&gt;localhost&lt;/em&gt; on port 8888 which is default the port &lt;a href="http://www.fiddlertool.com/fiddler/" title="HTTP Debugging Proxy"&gt;Fiddler&lt;/a&gt; is listening to.
The full name of the computer needs to be provided since Fiddler will &lt;a href="http://www.fiddlertool.com/Fiddler/help/hookup.asp" title="Explanation on why Fiddler will bypass localhost and 127.0.0.1"&gt;bypass&lt;/a&gt; &lt;em&gt;localhost&lt;/em&gt;.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="python geshifilter-python" style="font-family:monospace;"&gt;# Import Directives
# ....
&amp;nbsp;
control = HTTPPluginControl.getConnectionDefaults()
control.setProxyServer(&amp;quot;localhost&amp;quot;, 8888)
control.setFollowRedirects(0)
&amp;nbsp;
test1 = Test(1, &amp;quot;WebService&amp;quot;)
request1 = test1.wrap(HTTPRequest())
&amp;nbsp;
class TestRunner:
	def __call__(self):		
		request1.GET(&amp;quot;http://MyComputer/MyApplication/PresentationService.ashx&amp;quot;)&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Adding a new request is a matter of creating a new test and wrap it as a HTTP request. The following script simulates two requests:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="python geshifilter-python" style="font-family:monospace;"&gt;# Import Directives
# ....
&amp;nbsp;
test1 = Test(1, &amp;quot;WebService&amp;quot;)
request1 = test1.wrap(HTTPRequest())
&amp;nbsp;
test2 = Test(1, &amp;quot;CSSFile&amp;quot;)
request2 = test1.wrap(HTTPRequest())
&amp;nbsp;
class TestRunner:
	def __call__(self):		
		request1.GET(&amp;quot;http://localhost/MyApplication/PresentationService.ashx&amp;quot;)
                request2.GET(&amp;quot;http://localhost/MyApplication/Style.css&amp;quot;)&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
The load test can be written manually or can be generated through the &lt;a href="http://grinder.sourceforge.net/g3/tcpproxy.html" title="Instructions related to the TCP proxy"&gt;TCP proxy&lt;/a&gt; provided with &lt;em&gt;The Grinder&lt;/em&gt;. 
Starting the TCP proxy to generate the load case could be done through yet another batch file:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;call &amp;quot;C:\Documents and Settings\pierre rebours\Desktop\grinder\setGrinderEnv.cmd&amp;quot;
java -cp %CLASSPATH% net.grinder.TCPProxy -console -http &amp;gt; proxy-output.py&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
&lt;em&gt;The Grinder&lt;/em&gt; remains a simple tool to set up and start testing web applications under heavy load. 
Running Windows Performance Monitor in parallel allows correlating the number of requests per second (RPS) with underlying performance counters.
I would recommend &lt;em&gt;The Grinder&lt;/em&gt; to developers who would like to ensure that their web applications respond well under stress before handing them to more experimented testers knowing the in-and-outs of more sophisticated testing tools.
&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Tue, 16 Dec 2008 15:51:04 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">57 at http://pierrerebours.com</guid>
  </item>
  <item>
    <title>Context Connection and SQLCLR Functions</title>
    <link>http://pierrerebours.com/blog/context-connection-and-sqlclr-functions</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/microsoft/sql-server/tsql"&gt;TSQL&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/microsoft/net"&gt;.NET&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/sqlclr"&gt;SQLCLR&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
For one of the projects I have worked on recently, a set of variables needed to be computed for each product and for each month of the year on a regular basis. 
The product data was stored in SQL Server 2005 SP2.
The computed volume was quite large since around 60 variables x 120 products x 12 months = &lt;a name="result-size"&gt;86,400 results&lt;/a&gt; needed to be calculated every time and be stored in the result table.
The business requirements were the following:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The calculated variables were based on complex business rules which were quite tricky to be implemented in TSQL.&lt;/li&gt;
&lt;li&gt;Each variable related to a product had to use input from various tables.&lt;/li&gt;
&lt;li&gt;Variables related to a given product were independent of other products.&lt;/li&gt;
&lt;li&gt;On the other hand, variables were sometimes based on others variables for the same product.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
It was decided to express the business rules using a .NET language such as C# and to create a &lt;em&gt;Table-Valued Function&lt;/em&gt; (&lt;a href="http://msdn.microsoft.com/en-us/library/ms189876.aspx"&gt;TVF&lt;/a&gt;) using the &lt;a href="http://en.wikipedia.org/wiki/SQLCLR" title="SQL CLR"&gt;CLR&lt;/a&gt;. &lt;a href="http://www32.brinkster.com/srisamp/sqlArticles/article_46.htm"&gt;Srinivas Sampath&lt;/a&gt; wrote a good introduction on how to implement a TVF in .NET. 
&lt;/p&gt;

&lt;!--break--&gt;

&lt;p&gt;
The TVF called &lt;code&gt;ufnComputeProduct&lt;/code&gt; takes the &lt;code&gt;Product&lt;/code&gt; code as the only parameter.
The function returns a table with the following columns: the &lt;code&gt;Product&lt;/code&gt; code, the &lt;code&gt;VariableName&lt;/code&gt;, the &lt;code&gt;MonthID&lt;/code&gt;, and the &lt;code&gt;VariableValue&lt;/code&gt;.
A &lt;code&gt;CROSS APPLY&lt;/code&gt; runs all the available products against the function and stores the result set in the &lt;code&gt;VersionedResults&lt;/code&gt; table. As mentioned &lt;a href="#result-size"&gt;previously&lt;/a&gt;, this query would insert around 85,000 records every time.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="sql geshifilter-sql" style="font-family:monospace;"&gt;INSERT INTO VersionedResults
	(ResultSetVersionID, Product, VariableName, MonthID, VariableValue)
	SELECT @ResultSetVersionID AS ResultSetVersionID,
			Result.Product,
			Result.VariableName, Result.MonthID, Result.VariableValue
	FROM Product
	CROSS APPLY ufnComputeProduct(Products.Product) AS Result		&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Computing all the variables related to a given product requires to pull various input data from the database. In the .NET code of the user-function, a stored procedure is called in order to return all the relevant input data. The &lt;a href="http://msdn.microsoft.com/en-us/library/ms131053.aspx"&gt;context connection&lt;/a&gt; is used since the stored procedure and the CLR function are executed within the same pipe:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;using (SqlConnection connection = new SqlConnection(&amp;quot;context connection=true&amp;quot;))
using (SqlCommand sqlCommand = new SqlCommand())           
{
      connection.Open();
&amp;nbsp;
      // Execute the store procedure
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Unfortunately, running the &lt;code&gt;CROSS APPLY&lt;/code&gt; SQL statement returns the following error:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;Msg 3991, Level 16, State 1, Procedure uspCompute, Line 60
The context transaction which was active before entering user defined routine, trigger or aggregate &amp;quot;ufnComputeProduct&amp;quot; has been ended inside of it, which is not allowed. Change application logic to enforce strict transaction nesting.
The statement has been terminated.&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
After searching on the Internet, I have discovered that this error message is also related to rollbacks within SQLCLR code (See &lt;a href="http://msdn.microsoft.com/en-us/library/ms131093.aspx"&gt;transaction&lt;/a&gt; or &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=865299"&gt;trigger&lt;/a&gt; rollbacks).
On the other hand, running the &lt;code&gt;CROSS APPLY&lt;/code&gt; query without the &lt;code&gt;INSERT&lt;/code&gt; statement does not raise any error. 
The problem is therefore related to the fact that the CLR function is called within the transaction scope of the &lt;code&gt;INSERT&lt;/code&gt; statement.
It turns out that the solution is &lt;em&gt;not to close&lt;/em&gt; the context connection:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;// We need to remove the connection out of the using statement
SqlConnection connection = new SqlConnection(&amp;quot;context connection=true&amp;quot;);
&amp;nbsp;
using (SqlCommand sqlCommand = new SqlCommand())           
{
      connection.Open();
&amp;nbsp;
      // Execute the store procedure
}
// It will work!&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
Calling methodically &lt;code&gt;Dispose&lt;/code&gt; on all the disposable objects which have been created in our code has turned against us.
I personally believe that calling &lt;code&gt;Dispose&lt;/code&gt; on a context connection should not have any side effect. The &lt;code&gt;SqlConnection&lt;/code&gt; implementation should have detected that is was a context connection and should have never closed the connection. The connection was created by SQL Server and should be closed by SQL Server, irregardless of the user code.
&lt;/p&gt;

&lt;p&gt;
One could however argue that calling a stored procedure within a CLR function should not be allowed since calling a stored procedure within a TSQL function is not allowed in SQL Server. 
However, &lt;a href="http://msdn.microsoft.com/en-us/library/aa175782.aspx" title="Breaking the Spell on Stored Procedures and Functions"&gt;Herts Chen&lt;/a&gt; in an article on SQL Server 2000 mentioned workarounds with &lt;a href="http://msdn.microsoft.com/en-us/library/ms188427.aspx"&gt;&lt;code&gt;OPENQUERY&lt;/code&gt;&lt;/a&gt;.
With SQL Server 2005, using stored procedures within a CLR function can be an acceptable workaround, as long as you are careful with the context connection.
&lt;/p&gt; &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Mon, 20 Oct 2008 16:48:00 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">55 at http://pierrerebours.com</guid>
  </item>
  <item>
    <title>Review of SQL Server 2005 Reporting Services, Essential Skills for Database Professionals</title>
    <link>http://pierrerebours.com/blog/review-sql-server-2005-reporting-services-essential-skills-database-professionals</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/microsoft/sql-server"&gt;SQL Server&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/microsoft/sql-server/ssrs"&gt;SSRS&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/sql"&gt;SQL&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-taxonomy-vocabulary-5 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Stories:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/stories/review"&gt;Review&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
&lt;a class="floating-image" href="http://www.amazon.com/Microsoft-Server-2005-Reporting-Services/dp/B000SBTWE6"&gt;
  &lt;img src="http://pierrerebours.com/sites/default/files/SQLServer2005ReportingServices_BookCover.jpg" width="240" height="240" alt="Book Cover" /&gt;
&lt;/a&gt;
As I wanted to have a complete view of the features delivered by &lt;a href="http://www.microsoft.com/sql/technologies/reporting/default.mspx" title="Introduction of the product on the Microsoft site"&gt;SQL Server Reporting Services&lt;/a&gt; (SSRS in short), and yet knowing how to use the product in real-world scenarios, I got a book titled &lt;em&gt;Microsoft SQL Server 2005 Reporting Services&lt;/em&gt; by Brian Larson.
&lt;/p&gt;

&lt;p&gt;
The book is divided into three parts. All the examples are based on the &lt;em&gt;Galaxy&lt;/em&gt; database, a fictional inter-galactic delivery service.
The first version of the book was based on the sample database coming with SQL Server 2005, &lt;em&gt;Adventure Works&lt;/em&gt;, but it seems that it was worth to develop a new sample database for the new edition of the book. 
But, it can make the TSQL queries a little bit harder to understand.
&lt;/p&gt;
&lt;!-- break --&gt;

&lt;h2&gt;Part 1, Getting Started&lt;/h2&gt;
&lt;p&gt;
The first chapters give you an overview of the architecture of the reporting tool, the installation, and the different options of deployment. 
It is enough for a solution architect to get a clear view of the components, but will probably fall short for a system administrator.
Just for the record, the author states on p. 29 that the &lt;a href="#report-builder"&gt;Report Builder&lt;/a&gt; is available only in the Enterprise version of SQL Server, which is not correct: the Standard Edition allows the use of the Report Builder as well.
&lt;/p&gt;

&lt;h2&gt;Part 2, Report Authoring&lt;/h2&gt;
&lt;p&gt;
The second part focuses on building the reports. The author goes through the wizards first, the basic reports from scratch, and finally advanced reporting. This part is where the value of the book lays.
Each chapter guides us through the creation of reports from beginning to end. On average, the reader will be exposed to five to seven reports each chapter. Each report covers a specific set of functionalities in SSRS. By the end of the second part, you should know all the functionalities available in the Report Designer, and this is a good feeling.
&lt;/p&gt;

&lt;p&gt;
The reader needs to be in front of the computer, because the book goes through all the steps to create the reports. At the end of each report built under the supervision of the author, there is a debriefing section called &lt;em&gt;task notes&lt;/em&gt; which outlines the functionalities and tricks used for this report.
&lt;/p&gt;

&lt;p&gt;
Being guided through the report step by step is fine at the beginning, but starts to be repetitive as most of the steps are atomic and repeated over and over. Count on having 50 steps on average for each report built.
Some of the steps are about configuring the visual look of the report which is very frustrating from a developer perspective.
On the other hand, this book may be perfect not for DBAs or developers, but the business users. All the steps are thoroughly explained and it is difficult to go off-track.
Offer this book to your customer, and you will teach them how to fish their own advanced reports.
&lt;/p&gt;

&lt;h2&gt;Part 3, Report Serving&lt;/h2&gt;
&lt;p&gt;
The last part focuses on the &lt;em&gt;Report Manager&lt;/em&gt;, the built-in website which is used to deploy and distribute the reports. 
Similarly to the second part, all the functionalities are covered through exercises. It is a part worth reading for people in charge of deploying and distributing reports. Report Manager is quite advanced in term of authorization and configuration, and could therefore be used as a front-end application for small-sized projects.
The last chapter of the book focuses on the available options to integrate reports seamlessly with existing applications. 
&lt;/p&gt;

&lt;h2&gt;Annexes&lt;/h2&gt;
&lt;p&gt;
Finally, appendixes cover the report definition language and the web service interface of the Report manager. These types of reference annexes are a good way to increase artificially the size of the book, and do not offer a terrific value.
However, the last annex is about &lt;a name="report-builder"&gt;&lt;em&gt;Report Builder&lt;/em&gt;&lt;/a&gt;, the Ad Hoc reporting tool for Power Users who do not have Report Designer and Visual Studio installed on their machine.  
The author goes also through the creation of the &lt;em&gt;Report Model&lt;/em&gt; which is be the only type of data source that Report Builder can use. 
&lt;/p&gt;


&lt;p&gt;
I recommend this book for people wanted to author reports and deploys them.
DBAs and developers may find the book to be a little bit slow, but they will get a good value by going through all the exercises.
&lt;/p&gt;

&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Sat, 04 Oct 2008 08:55:59 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">53 at http://pierrerebours.com</guid>
 <comments>http://pierrerebours.com/blog/review-sql-server-2005-reporting-services-essential-skills-database-professionals#comments</comments>
  </item>
  <item>
    <title>Testing Equality Operators with NUnit</title>
    <link>http://pierrerebours.com/blog/testing-equality-operators-nunit</link>
    <description>&lt;div class="field-group-format group_tag field-group-div group-tag clearfix speed-fast effect-none"&gt;&lt;h3&gt;&lt;span&gt;Published in:&lt;/span&gt;&lt;/h3&gt;&lt;div class="field field-name-taxonomy-vocabulary-2 field-type-taxonomy-term-reference field-label-inline clearfix"&gt;&lt;div class="field-label"&gt;Published in:&amp;nbsp;&lt;/div&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/microsoft/net/csharp"&gt;C#&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/microsoft/net"&gt;.NET&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item even"&gt;&lt;a href="/category/technologies/tdd"&gt;TDD&lt;/a&gt;&lt;/div&gt;&lt;div class="field-item odd"&gt;&lt;a href="/category/technologies/nunit"&gt;NUnit&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-body field-type-text-with-summary field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;div class="field-item even"&gt;&lt;p&gt;
Any class or structure in .NET can define the &lt;a href="http://msdn.microsoft.com/en-us/library/53k8ybth.aspx"&gt;&lt;em&gt;equality&lt;/em&gt;&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/3tz250sf.aspx"&gt;&lt;em&gt;inequality&lt;/em&gt;&lt;/a&gt; operators. 
Implementing such operators, however, can be error-prone. The operators therefore need to be validated by unit tests.
We will first discuss the challenges of writing such unit tests.
We will then review how just &lt;em&gt;one&lt;/em&gt; new NUnit &lt;a href="http://www.nunit.org/index.php?p=constraintModel&amp;amp;r=2.4.1"&gt;constraint&lt;/a&gt; can help writing thorough tests for the equality and inequality operators.
&lt;/p&gt;

&lt;p&gt;
The implementations of the equality and inequality operators are presented below for a simple &lt;code&gt;Customer&lt;/code&gt; class: two customers are expected to be equal if they have the same name.
Refer to the Microsoft &lt;a href="http://msdn.microsoft.com/en-us/library/ms173147.aspx"&gt;guidelines&lt;/a&gt; for further details.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;class Customer
{
    private readonly string name;
&amp;nbsp;
    public Customer(string name)
    {
        if (name == null) { 
           throw new ArgumentNullException();
        } 
        this.name = name;
    }
&amp;nbsp;
    public string Name
    {
        get
        {
            return name;
        }
    }
&amp;nbsp;
    public override bool Equals(object obj)
    {
        Customer customer = obj as Customer;
        if (customer != null)
        {
            return this == customer;
        }
        else
        {
            return false;
        }
    }
&amp;nbsp;
    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
&amp;nbsp;
    public static bool operator ==(Customer lhs, Customer rhs)
    {
        if (object.ReferenceEquals(lhs, rhs))
        {
            return true;
        }
        else if ((object)lhs == null || (object)rhs == null)
        {
            return false;
        }
        else
        {
            return lhs.Name == rhs.Name;
        }
    }
&amp;nbsp;
    public static bool operator !=(Customer lhs, Customer rhs)
    {
        return !(lhs == rhs);
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Such implementations typically use &lt;code&gt;lhs&lt;/code&gt; and &lt;code&gt;rhs&lt;/code&gt; as names for the parameters of the equality and inequality operators.
&lt;code&gt;lhs&lt;/code&gt; is the abbreviation for &lt;a href="http://en.wikipedia.org/wiki/Left-hand_side_and_right-hand_side_of_an_equation" title="Sides of an equation"&gt;&lt;em&gt;left-hand side&lt;/em&gt;&lt;/a&gt;.
Similarly, &lt;code&gt;rhs&lt;/code&gt; stands for &lt;em&gt;right-hand side&lt;/em&gt;.
For the remaining of this discussion, &lt;em&gt;equality operators&lt;/em&gt; will refer to both the equality and inequality operators.
&lt;/p&gt;

&lt;h2&gt;&lt;a name="semantics"&gt;Semantics of the Equality Operators&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;
Equality operators allow to express equality relations between two objects using a more natural syntax than the overridden &lt;a href="http://msdn.microsoft.com/en-us/library/system.object.aspx"&gt;&lt;code&gt;Equals&lt;/code&gt;&lt;/a&gt; method inherited from &lt;a href="http://msdn.microsoft.com/en-us/library/system.object.aspx"&gt;&lt;code&gt;object&lt;/code&gt;&lt;/a&gt;, the base type of the .NET run-time. 
Fully supporting equality and inequality relations requires to respect three &lt;a href="http://en.wikipedia.org/wiki/Equality_(mathematics)" title="Equality in mathematics"&gt;semantics&lt;/a&gt;:  
&lt;a href="http://en.wikipedia.org/wiki/Reflexive_relation"&gt;reflexivity&lt;/a&gt;,
&lt;a href="http://en.wikipedia.org/wiki/Symmetric_relation"&gt;symmetry&lt;/a&gt;, and
&lt;a href="http://en.wikipedia.org/wiki/Transitive_relation"&gt;transitivity&lt;/a&gt;.
Testing the semantics of the operators  can be done with NUnit &lt;a href="http://www.nunit.org/index.php?p=constraintModel&amp;amp;r=2.4.8" title="The constraint model with NUnit"&gt;constraints&lt;/a&gt;.
Given any references &lt;code&gt;c1&lt;/code&gt;, &lt;code&gt;c2&lt;/code&gt;, and &lt;code&gt;c3&lt;/code&gt; of type &lt;code&gt;Customer&lt;/code&gt;, the equality operators should be:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reflexive.
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Assert.That(c1 == c1, Is.True);
Assert.That(c1 != c1,  Is.False);&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;symmetric.
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Assert.That( (c1 == c2 &amp;amp;&amp;amp; c2 == c1) || (c1 != c2 &amp;amp;&amp;amp; c2 != c1), Is.True);&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;transitive.
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;if (c1 == c2 &amp;amp;&amp;amp; c2 == c3) {
   Assert.That(c1 == c3, Is.True);
}
if (c1 != c2 &amp;amp;&amp;amp; c2 != c3) {
   Assert.That(c1 != c3, Is.True);
} &lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Equality operators in .NET should also behave in relation with the &lt;a href="http://msdn.microsoft.com/en-us/library/system.object.aspx"&gt;&lt;code&gt;Equals&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.string.gethashcode.aspx"&gt;&lt;code&gt;GetHashCode&lt;/code&gt;&lt;/a&gt; methods. Like the equality operators, &lt;code&gt;Equals&lt;/code&gt; should also be reflective, symmetric, and transitive.
Note that in the following piece of code, &lt;code&gt;c1&lt;/code&gt; and &lt;code&gt;c2&lt;/code&gt; are assumed to be non-null.
Tests of the reflexivity, symmetry, and transitivity of &lt;code&gt;Equals&lt;/code&gt; are also omitted for brevity here.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Assert.IsTrue( (c1 == c2 &amp;amp;&amp;amp; c1.Equals(c2)) || (c1 != c2 &amp;amp;&amp;amp; !c1.Equals(c2));
Assert.IsTrue( (c1 == c2 &amp;amp;&amp;amp; c1.GetHashCode() == c2.GetHashCode()) || (c1 != c2 &amp;amp;&amp;amp; c1.GetHashCode() == c2.GetHashCode());&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Furthermore, any non-null reference &lt;code&gt;c&lt;/code&gt; of type &lt;code&gt;Customer&lt;/code&gt; should be expected &lt;em&gt;not&lt;/em&gt; to be equal to the null reference.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Customer nullCustomer = null;
&amp;nbsp;
Assert.That(c.Equals(null), Is.False);
&amp;nbsp;
Assert.That(c == (Customer)null, Is.False);
Assert.That((Customer)null == c1, Is.False);
&amp;nbsp;
Assert.That(c != (Customer)null, Is.True);
Assert.That(c == (Customer)null, Is.False);&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
&lt;a name="null-test"&gt;Similarly&lt;/a&gt;, the static equality operators should behave properly when all the input parameters are null. Testing such extreme cases is important as developers, including myself, sometimes forget to deal appropriately with null references.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Assert.That( (Customer)null == (Customer)null, Is.True);&lt;/pre&gt;&lt;/div&gt;


&lt;h2&gt;Challenges of Testing&lt;/h2&gt;
&lt;p&gt;
Using equality operators allows to create rich but syntaxically simple expressions which are easy to read and maintain. 
Therefore, an application may define a lot of equality operators. As mentioned previously, testing the newly implemented operators consists in testing if the operators respect the &lt;a href="#semantic"&gt;inherent semantics&lt;/a&gt; and are consistent with &lt;code&gt;Equals&lt;/code&gt; and &lt;code&gt;GetHashCode&lt;/code&gt; methods.
&lt;/p&gt;

&lt;p&gt;
Testing properly the equality operators is finally more complex than expected as the number of potential cases to test is quite large.
Furthermore, tests need also to be run for two references of &lt;code&gt;Customer&lt;/code&gt; expected to be unequal. 
Consequently, the NUnit &lt;a href="http://www.nunit.org/index.php?p=assertions&amp;amp;r=2.4.8"&gt;assertions&lt;/a&gt; should to be factorized in order to be reused across multiple &lt;a href="http://en.wikipedia.org/wiki/Test_fixture"&gt;test fixtures&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;&lt;a name="compile-time"&gt;But Equality Operators are Resolved during Compilation&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;
Consider the following first draft which attempts to factorize the assertions into the function &lt;code&gt;AssertEqualityForEqualObject&lt;/code&gt;.
This function is meant to test not only the &lt;code&gt;Customer&lt;/code&gt; class, but also other types such as the &lt;code&gt;Supplier&lt;/code&gt; class or the &lt;code&gt;ZipCode&lt;/code&gt; structure for example.
Since the only commonality between all the .NET types is the type &lt;code&gt;object&lt;/code&gt;, our first draft will have two input parameters &lt;code&gt;obj1&lt;/code&gt; and &lt;code&gt;obj2&lt;/code&gt; of type &lt;code&gt;object&lt;/code&gt;.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;void AssertEqualityForEqualObject(object obj1, object obj2) {
   // Testing null arguments is omitted in this example
&amp;nbsp;
   Assert.That(obj1.Equals(obj2), Is.True); 
   Assert.That(obj2.Equals(obj1), Is.True);
   . . . .    
   // This statement will not work as indented!
   // Object.ReferenceEquals(obj1, obj2) will be called instead of Customer.operator==(obj1, obj2)
   Assert.That(obj1 == obj2, Is.True);
   . . . . &lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
The second assert will not work as indented because the decision of choosing the appropriate &lt;em&gt;static&lt;/em&gt; operator is made at compile-time.
Hence, the equality operator defined for the type &lt;code&gt;object&lt;/code&gt; will always be called at run-time. In other words, the second assertion just checks if &lt;code&gt;obj1&lt;/code&gt; and &lt;code&gt;obj2&lt;/code&gt; are the same reference.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx"&gt;Generics&lt;/a&gt; will not work either for the same reason: &lt;code&gt;operator ==&lt;/code&gt; is resolved at compilate-time, not at run-time.
Compiling the following piece of code will lead to the following error: &lt;code&gt;Operator '==' cannot be applied to operands of type 'T' and 'U'&lt;/code&gt;.
&lt;a href="http://forums.msdn.microsoft.com/en-US/csharplanguage/thread/6317290d-bbfb-46f6-812b-7f4252ce3f27/"&gt;Comments&lt;/a&gt; have been made on this issue.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;class EqualityAssertion&amp;lt;T, U&amp;gt;
{
    public bool Test(T obj1, U obj2)
    {
        return obj1 == obj2;
    }
}&lt;/pre&gt;&lt;/div&gt;


&lt;h3&gt;Value and Reference Types&lt;/h3&gt;
&lt;p&gt;
As previously &lt;a href="#null-test"&gt;mentioned&lt;/a&gt;, it is important to test cases with null parameters. However, such tests on the equality operators is irrelevant for &lt;a href="http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx"&gt;value types&lt;/a&gt;.
&lt;a href="http://csharp102.blogspot.com/2005_12_01_archive.html"&gt;Abstract Data Type&lt;/a&gt; (ADT) like the &lt;code&gt;PostCode&lt;/code&gt; or &lt;code&gt;Money&lt;/code&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ah19swz4.aspx"&gt;structures&lt;/a&gt; usually rely on equality operators.
But it is expected that testing the &lt;code&gt;Equals&lt;/code&gt; method with a null parameter on a value type will always return false:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Assert.That(DateTime.Now.Equals(null), Is.False);&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;NUnit Integration&lt;/h3&gt;
&lt;p&gt;
The challenges of implementing a generic test for the equality operators have now been outlined.
Several paths of action are possible to implement the solution with NUnit.
One way is to inherit &lt;a href="http://en.wikipedia.org/wiki/Test_fixture"&gt;test fixtures&lt;/a&gt; from a base class which will have factorized the assertions for equality operators.
Another way consists in extending NUnit by creating a new type of &lt;a href="http://www.nunit.org/index.php?p=constraintModel&amp;amp;r=2.4.8" title="The constraint model with NUnit"&gt;constraint&lt;/a&gt;. This constraint evaluates whether or not two instances expected to be equal follow the semantics of the equality operators. 
&lt;/p&gt;

&lt;p&gt;
&lt;a name="download"&gt;
&lt;img src="http://farm4.static.flickr.com/3161/2799685860_b9f2d9e1ed_o.png" width="24" height="24" alt="Download icon" class="floating-image" /&gt;
&lt;/a&gt;
In the implementation presented in this article, I have chosen to create a NUnit constraint called &lt;code&gt;EqualityOperatorConstraint&lt;/code&gt;.
The code is available from my Subversion &lt;a href="https://pierrerebours.devguard.com/svn/default/dotnet/lab/EqualityOperatorConstraint/"&gt;directory&lt;/a&gt;. Please refer to the &lt;a href="http://pierrerebours.com/subversion-instructions"&gt;instruction&lt;/a&gt; to download the tarballs.
&lt;/p&gt;

&lt;h2&gt;Equality Operator Constraint&lt;/h2&gt;
&lt;p&gt;
Let's review the details of the implementation of &lt;code&gt;EqualityOperatorConstraint&lt;/code&gt;.
We will first tackle on how equality operators can be resolved not at &lt;a href="#compile-time"&gt;compile-time&lt;/a&gt; but at run-time.
&lt;/p&gt;

&lt;h3&gt;IStaticEqualityOperatorProvider&lt;/h3&gt;
&lt;p&gt;
The interface &lt;code&gt;IStaticEqualityOperatorProvider&lt;/code&gt; is used to resolve the static equality operators at run-time. This interface defines two methods. As their names suggest, &lt;code&gt;EvaluateStaticEqualEqualOperator&lt;/code&gt; and &lt;code&gt;EvaluateStaticNotEqualOperator&lt;/code&gt; return the result for the expressions &lt;code&gt;lhs == rhs&lt;/code&gt; and &lt;code&gt;lhs != rhs&lt;/code&gt;, respectively. 
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;public interface IStaticEqualityOperatorProvider
{
       bool EvaluateStaticEqualEqualOperator(object lhs, object rhs);
       bool EvaluateStaticNotEqualOperator(object lhs, object rhs);        
}   &lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Several implementations are provided:
&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;ReflectiveStaticEqualityOperatorProvider&amp;lt;T&amp;gt;&lt;/code&gt; relies on &lt;a href="http://en.wikipedia.org/wiki/.NET_metadata"&gt;reflection&lt;/a&gt; to call the correct &lt;code&gt;operator==&lt;/code&gt; and &lt;code&gt;operator!=&lt;/code&gt; functions.
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;private bool? InvokeStaticOperator(T lhs, T rhs, string methodName)
{
    MethodInfo mi = typeof(T).GetMethod(methodName, BindingFlags.Static | BindingFlags.Public, null, new Type[] {
            typeof(T),
            typeof(T)},
       null);
&amp;nbsp;
    if (mi != null)
    {
        object result = mi.Invoke(null, new object[] { lhs, rhs });
        if (!(result is bool))
        {
            throw new InvalidCastException();
        }
        return (bool)result;
    }
    else
    {
        return null;
    }
}
&amp;nbsp;
public override bool EvaluateStaticEqualEqualOperator(T lhs, T rhs)
{
    bool? result = InvokeStaticOperator(lhs, rhs, &amp;quot;op_Equality&amp;quot;);
    if (result == null)
    {
        throw new ReflectiveStaticEqualEqualOperatorNotFound(string.Format(&amp;quot;operator== is not defined in \&amp;quot;{0}\&amp;quot;&amp;quot;, typeof(T).Name));
    }
    else
    {
        return result.Value;
    }
}&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DelegatedStaticEqualityOperatorProvider&lt;/code&gt; accepts delegates as parameters of the constructor.
It allows to come up with an inline implementation of the provider using &lt;a href="http://msdn.microsoft.com/en-us/library/ah19swz4.aspx"&gt;anonymous&lt;/a&gt; methods.
The following piece of code create a provider for &lt;a href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx"&gt;&lt;code&gt;DateTime&lt;/code&gt;&lt;/a&gt;:
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;IStaticEqualityOperatorProvider provider = new DelegatedStaticEqualityOperatorProvider&amp;lt;DateTime&amp;gt;(
    delegate(DateTime lhs, DateTime rhs)
    {
       return lhs == rhs;
    },
    delegate(DateTime lhs, DateTime rhs)
    {
      return lhs != rhs;
    });&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Aggregate of Atomic Constraints&lt;/h3&gt;
&lt;p&gt;
Creating a new constraint in NUnit consists in implementing two methods of the abstract class &lt;code&gt;Constraint&lt;/code&gt;: &lt;code&gt; bool Matches(object actual)&lt;/code&gt; and &lt;code&gt;void WriteDescriptionTo(MessageWriter writer)&lt;/code&gt;.
In the current &lt;a href="#download"&gt;implementation&lt;/a&gt;, &lt;code&gt;EqualityOperatorConstraint&lt;/code&gt; constructs a &lt;a href="http://www.nunit.org/index.php?p=compoundConstraints&amp;amp;r=2.4.8"&gt;compound&lt;/a&gt; constraint using &lt;code&gt;&amp;amp;&lt;/code&gt; (with &lt;code&gt;AndConstraint&lt;/code&gt;) and &lt;code&gt;|&lt;/code&gt; (with &lt;code&gt;OrConstraint&lt;/code&gt;) operators to add all the &lt;a href="#assert"&gt;atomic constraints&lt;/a&gt; testing the semantic of the equality operators and the behavior of the &lt;code&gt;Equals&lt;/code&gt; and &lt;code&gt;GetHashCode&lt;/code&gt; methods.
&lt;/p&gt;

&lt;h3&gt;Using the Equality Constraints&lt;/h3&gt;
&lt;p&gt;
Let's go back to our first example with the &lt;code&gt;Customer&lt;/code&gt; class.
Testing the equality operators as well as testing &lt;code&gt;Equals&lt;/code&gt; and &lt;code&gt;GetHashCode&lt;/code&gt; is just a matter of using the new &lt;code&gt;EqualityOperatorConstraint&lt;/code&gt; combined with &lt;code&gt;ReflectiveStaticEqualityOperatorProvider&amp;lt;Customer&amp;gt;&lt;/code&gt;.
The constraints comes with two flavors:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;EqualityOperatorConstraint&lt;/code&gt; evaluates if two references are expected to be &lt;em&gt;equal&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InequalityOperatorConstraint&lt;/code&gt; evaluates if two reference are expected to be &lt;em&gt;unequal&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;[Test]
public void TestCustomerWithEquality()
{
    Customer customer = new Customer(&amp;quot;James&amp;quot;);
    Constraint constraint = new EqualityOperatorConstraint(customer, new ReflectiveStaticEqualityOperatorProvider&amp;lt;Customer&amp;gt;());
&amp;nbsp;
    Assert.That(new Customer(&amp;quot;James&amp;quot;), constraint);        
}
&amp;nbsp;
[Test]
public void TestCustomerWithInequality()
{
    Customer customer = new Customer(&amp;quot;James&amp;quot;);
    Constraint constraint = new InequalityOperatorConstraint(customer, new ReflectiveStaticEqualityOperatorProvider&amp;lt;Customer&amp;gt;());
&amp;nbsp;
    Assert.That(new Customer(&amp;quot;David&amp;quot;), constraint);
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The NUnit model provides a description when a constraint fails. 
As mentioned previously, the &lt;code&gt;EqualityOperatorConstraint&lt;/code&gt; is an aggregate of simple constraints.
To avoid any verbose message, the description of the first constraint which fails is provided instead. 
Consider the following case where the equality operator of the &lt;code&gt;Customer&lt;/code&gt; class has been improperly implemented.
Instead of comparing the names, the operator compares the &lt;em&gt;length&lt;/em&gt; of the names.
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;class Customer
{
    private readonly string name;
&amp;nbsp;
    public Customer(string name)
    {
        this.name = name;
    }
&amp;nbsp;
    public string Name
    {
&amp;nbsp;
        get
        {
            return name;
        }
    }
&amp;nbsp;
&amp;nbsp;
    public override bool Equals(object obj)
    {
        Customer customer = obj as Customer;
        if (customer != null)
        {
            return this == customer;
        }
        else
        {
            return false;
        }
    }
&amp;nbsp;
    public override int GetHashCode()
    {
        return name.GetHashCode();
    }
&amp;nbsp;
    // Incorrect implementation of Customer. The lengths of the names are compared!
    public static bool operator ==(Customer lhs, Customer rhs)
    {
        if (object.ReferenceEquals(lhs, rhs))
        {
            return true;
        }
        else if ((object)lhs == null || (object)rhs == null)
        {
            return false;
        }
        else
        {
            return lhs.Name.Length == rhs.Name.Length;
        }
    }
&amp;nbsp;
    public static bool operator !=(Customer lhs, Customer rhs)
    {
        return !(lhs == rhs);
    }
&amp;nbsp;
    public override string ToString()
    {
        return Name;
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The case testing the &lt;em&gt;inequality&lt;/em&gt; between a customer called &lt;em&gt;James&lt;/em&gt; and &lt;em&gt;Williams&lt;/em&gt; will pass since the names are of different lengths.
However, testing the &lt;em&gt;inequality&lt;/em&gt; between &lt;em&gt;James&lt;/em&gt; and &lt;em&gt;Henry&lt;/em&gt; will fail with this error message:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Assert.That(new Customer(&amp;quot;Henry&amp;quot;), new InequalityOperatorConstraint(new Customer(&amp;quot;James&amp;quot;),
                    new ReflectiveStaticEqualityOperatorProvider&amp;lt;Customer&amp;gt;()));&lt;/pre&gt;&lt;/div&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;failed: operator ==(actual, expected) where &amp;quot;actual&amp;quot; was &amp;quot;Henry&amp;quot; and &amp;quot;expected&amp;quot; was &amp;quot;James&amp;quot;
Expected: False
Actual: True&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;
A related test with the &lt;em&gt;equality&lt;/em&gt; constraint this time will also fail because two customers with names of same length return a different hash code:
&lt;/p&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="csharp geshifilter-csharp" style="font-family:monospace;"&gt;Assert.That(new Customer(&amp;quot;Henry&amp;quot;), new EqualityOperatorConstraint(new Customer(&amp;quot;James&amp;quot;),
                   new ReflectiveStaticEqualityOperatorProvider&amp;lt;Customer&amp;gt;()));&lt;/pre&gt;&lt;/div&gt;
&lt;div class="geshifilter"&gt;&lt;pre class="text geshifilter-text" style="font-family:monospace;"&gt;failed: actual.GetHashCode() == expected.GetHashCode() where &amp;quot;actual&amp;quot; was &amp;quot;Henry&amp;quot; and &amp;quot;expected&amp;quot; was &amp;quot;James&amp;quot;
Expected: True
Actual: False&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
In order to fully cover the tested code, the &lt;code&gt;EqualityOperatorConstraint&lt;/code&gt; and the &lt;code&gt;InequalityOperatorConstraint&lt;/code&gt; need to be used with different pairs of instances expected to be equal and unequal, respectivelly.
The equality constraints can only carry out tests with the provided instances. So, as usual, keep an eye on &lt;a href="http://en.wikipedia.org/wiki/Code_coverage"&gt;code coverage&lt;/a&gt; while writing unit tests.
&lt;/p&gt;



&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="field field-name-upload field-type-file field-label-hidden"&gt;&lt;div class="field-items"&gt;&lt;/div&gt;&lt;/div&gt;</description>
     <pubDate>Wed, 03 Sep 2008 18:26:13 +0000</pubDate>
 <dc:creator>admin</dc:creator>
 <guid isPermaLink="false">50 at http://pierrerebours.com</guid>
  </item>
  </channel>
</rss>

