<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-31058042</id><updated>2011-11-17T11:01:26.809-05:00</updated><category term='humour'/><category term='iPhone'/><category term='MSBuild'/><category term='sql'/><category term='Apple'/><category term='TFS'/><category term='ASP.NET'/><title type='text'>the code monkey</title><subtitle type='html'>insomnia inspired ramblings from the procrastination station</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-31058042.post-7797691601815584597</id><published>2009-03-31T12:54:00.003-04:00</published><updated>2009-03-31T13:05:30.118-04:00</updated><title type='text'>Upload a directory to S3 with C#</title><content type='html'>&lt;a href="http://pastebin.com/f5ad9f68a"&gt;pastbin link&lt;/a&gt;

&lt;hr /&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
 font-size: small;
 color: black;
 font-family: Consolas, "Courier New", Courier, Monospace;
 background-color: #ffffff;
 /*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
 background-color: #f4f4f4;
 width: 100%;
 margin: 0em;
}

.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Threading;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Affirma.ThreeSharp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Affirma.ThreeSharp.Model;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; upload&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; Semaphore fileCounter;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; IThreeSharp service;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; MaxUploads = 6;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (args.Length &amp;lt; 4)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;                Console.Error.WriteLine(&lt;span class="str"&gt;"syntax: upload &amp;lt;aws-key&amp;gt; &amp;lt;aws-secretkey&amp;gt; &amp;lt;bucketname&amp;gt; &amp;lt;directory&amp;gt;"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;                Environment.Exit(1);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            ThreeSharpConfig config = &lt;span class="kwrd"&gt;new&lt;/span&gt; ThreeSharpConfig();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;            config.AwsAccessKeyID = args[0];&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;            config.AwsSecretAccessKey = args[1];&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;            config.ServiceType = ThreeSharpServiceType.S3;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;            config.IsSecure = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            config.ConnectionLimit = MaxUploads * 2;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;            ThreadPool.SetMaxThreads(MaxUploads, MaxUploads);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            service = &lt;span class="kwrd"&gt;new&lt;/span&gt; Affirma.ThreeSharp.Query.ThreeSharpQuery(config);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; bucketName = args[2];&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; directoryName = args[3].Trim();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;            var files = Directory.GetFiles(directoryName);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;            fileCounter = &lt;span class="kwrd"&gt;new&lt;/span&gt; Semaphore(0, files.Length);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;            ThreadPool.QueueUserWorkItem(ReportStatus);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; file &lt;span class="kwrd"&gt;in&lt;/span&gt; files)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;                BucketAddRequest add = &lt;span class="kwrd"&gt;new&lt;/span&gt; BucketAddRequest(bucketName);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;                add.Key = Path.GetFileName(file);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;                add.LoadStreamWithFile(file);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;                ThreadPool.QueueUserWorkItem(StartTransfer, add);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i=0; i&amp;lt;files.Length; ++i)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;                fileCounter.WaitOne();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ReportStatus(&lt;span class="kwrd"&gt;object&lt;/span&gt; state)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;            &lt;span class="kwrd"&gt;while&lt;/span&gt; (&lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;                Console.SetCursorPosition(0, 0);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var info &lt;span class="kwrd"&gt;in&lt;/span&gt; service.GetTransferInfos())&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;                    Console.WriteLine(&lt;span class="str"&gt;"{0} {1}/{2}"&lt;/span&gt;, info.Key, info.BytesTransferred, info.BytesTotal);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;                Thread.Sleep(TimeSpan.FromSeconds(2));&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  66:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  67:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  68:  &lt;/span&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; StartTransfer(&lt;span class="kwrd"&gt;object&lt;/span&gt; state)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  69:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  70:  &lt;/span&gt;            BucketAddRequest add = (BucketAddRequest)state;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  71:  &lt;/span&gt;            var response = service.BucketAdd(add);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  72:  &lt;/span&gt;            fileCounter.Release();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  73:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  74:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  75:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-7797691601815584597?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/7797691601815584597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2009/03/upload-directory-to-s3-with-c.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/7797691601815584597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/7797691601815584597'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2009/03/upload-directory-to-s3-with-c.html' title='Upload a directory to S3 with C#'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-4149894083786668683</id><published>2007-12-13T00:49:00.001-05:00</published><updated>2007-12-13T00:55:42.777-05:00</updated><title type='text'>DataReader Care &amp; Safety</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;As any good ADO developer will tell you "Make sure you close your connections!" or more plainly "Clean up after yourself". .NET has made this even easier with things like:
&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;using&lt;/span&gt; (&lt;span style='color:#2b91af'&gt;IDataReader&lt;/span&gt; r = cmd.ExecuteReader())&lt;br/&gt;{&lt;br/&gt;&lt;span style='color:green'&gt;    // logic here&lt;br/&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Recently though while doing some ASP.NET control development, I was stuck on how exactly the ASP.NET library team managed to close connections in certain scenarios. Specifically with the &lt;a href='http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.sqldatasource.aspx'&gt;SqlDataSource&lt;/a&gt; control and how was it making sure to clean up after the DataReader
 it uses for databinding.
&lt;/p&gt;&lt;p&gt;Let me first illustrate a scenario though in ASp.NET 1.0 data binding:
&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    Repeater r = GetYourRepeater();&lt;br/&gt;    &lt;span style='color:#2b91af'&gt;SqlConnection&lt;/span&gt; cn = GetYourSqlConnection();&lt;br/&gt;&lt;span style='color:#2b91af'&gt;    SqlCommand&lt;/span&gt; cmd = &lt;span style='color:blue'&gt;new&lt;/span&gt;
					&lt;span style='color:#2b91af'&gt;SqlCommand&lt;/span&gt;(&lt;span style='color:#a31515'&gt;"SELECT * FROM Table"&lt;/span&gt;, cn);&lt;br/&gt;    cn.Open();&lt;br/&gt;    r = cmd.ExecuteReader(CommandBehaviour.CloseConnection);&lt;br/&gt;    r.DataSource = r;&lt;br/&gt;    r.DataBind();
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;This code will actually clean up and close sql connection, but how? There's no "Close" method called or "Dispose" and no using statement. The fact that the connection is closed means SqlDataSource doesn't have to do anything special to make sure the DataReader is cleaned up. When I first started this investigation I didn't realise the above code would actually clean up the connection. 
&lt;/p&gt;&lt;p&gt;When I started to investigate I went right to &lt;a href='http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.sqldatasourceview.executeselect.aspx'&gt;SqlDataSourceView.ExecuteSelect&lt;/a&gt; which does the actual work of the data binding select. With some reflector work I saw that the DataReader was being executed with the &lt;a href='http://msdn2.microsoft.com/en-us/library/system.data.commandbehavior.aspx'&gt;CommandBehaviour.CloseConnection&lt;/a&gt;. I knew though that all this meant was that if you closed the DataReader you're underlying connection would be closed. 
&lt;/p&gt;&lt;p&gt;ExecuteSelect though just returns an IEnumerable. So I looked through various databinding controls looking for a cast to IDataReader and Close method being called, but I didn't find any. So I thought perhaps it's something with the DataReader itself and CommandBehaviour.CloseConnection. I suspected there was some code in DataReader that if you had that flag set and enumerated through the whole connection it would close the reader. The documentation for CommandBehaviour didn't say anything about this, but wierder things have happened.
&lt;/p&gt;&lt;p&gt;So I wrote a simple program to test this:
&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:#2b91af'&gt;    SqlConnection&lt;/span&gt; cn = &lt;span style='color:blue'&gt;new&lt;/span&gt;
					&lt;span style='color:#2b91af'&gt;SqlConnection&lt;/span&gt;(&lt;span style='color:#a31515'&gt;"Data Source=HERC;Initial Catalog=MAIN_Development;UserId=WebClientRW;Password=smooth"&lt;/span&gt;);&lt;br/&gt;&lt;span style='color:#2b91af'&gt;    SqlCommand&lt;/span&gt; cmd = &lt;span style='color:blue'&gt;new&lt;/span&gt;
					&lt;span style='color:#2b91af'&gt;SqlCommand&lt;/span&gt;(&lt;span style='color:#a31515'&gt;"SELECT * FROM _EventRegPeriod"&lt;/span&gt;, cn);&lt;br/&gt;    cn.Open();&lt;br/&gt;    &lt;span style='color:#2b91af'&gt;IDataReader&lt;/span&gt; r = cmd.ExecuteReader();&lt;br/&gt;    &lt;span style='color:blue'&gt;while&lt;/span&gt; (r.Read())&lt;br/&gt;      {&lt;br/&gt;          &lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(r[&lt;span style='color:#a31515'&gt;"ID"&lt;/span&gt;]);&lt;br/&gt;    }&lt;br/&gt;    &lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(r.IsClosed);&lt;br/&gt;    &lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(cn.State);&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;But the output of this program clearly showed both the reader and the connection were still open. What gives?? I was sure though I was on the right track. I checked again how Repeater used the data it got from the DataSource. It was using the IEnumerable interface though. Was this it? Was there some magic when you accessed a DataReader as an IEnumerable?&lt;span style='font-family:Courier New; font-size:10pt'&gt;
				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Yes, Virginia, there is.
&lt;/p&gt;&lt;p&gt;When I replaced the while loop above with the following foreach loop&lt;br/&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    foreach&lt;/span&gt; (&lt;span style='color:#2b91af'&gt;IDataRecord&lt;/span&gt; rec &lt;span style='color:blue'&gt;in&lt;/span&gt; r)&lt;/span&gt;&lt;br/&gt;    &lt;span style='font-family:Courier New; font-size:10pt'&gt;{&lt;/span&gt;&lt;br/&gt;        &lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(rec[&lt;span style='color:#a31515'&gt;"ID"&lt;/span&gt;]);&lt;/span&gt;&lt;br/&gt;    &lt;span style='font-family:Courier New; font-size:10pt'&gt;}&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;I found that both the reader and connection were closed. What was happening in GetEnumerator?? SqlDataReader.GetEnumerator was returning a &lt;a href='http://msdn2.microsoft.com/en-us/library/system.data.common.dbenumerator.aspx'&gt;DbEnumerator&lt;/a&gt;. what's more, DbEnumerator's &lt;a href='http://msdn2.microsoft.com/en-us/library/y78t5285.aspx'&gt;constructor&lt;/a&gt; takes an argument called... "closeReader"! This is True if the CommandBehaviour.CloseConnection is true. DbEnumerator is the magic that closes the connection if you fully enumerate a DataReader with CommandBehaviour.CloseConnection set.&lt;span style='font-family:Courier New; font-size:10pt'&gt;
				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Mystery solved, and one more place I can stop worrying about closing connections. Thanks .NET!! Sometimes I think I worry too much.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-4149894083786668683?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/4149894083786668683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2007/12/datareader-care-safety.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/4149894083786668683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/4149894083786668683'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2007/12/datareader-care-safety.html' title='DataReader Care &amp;amp; Safety'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-6368251616381253900</id><published>2007-02-07T23:45:00.000-05:00</published><updated>2007-02-08T10:46:40.724-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><category scheme='http://www.blogger.com/atom/ns#' term='MSBuild'/><title type='text'>MSBuild Bonanza (Part I)</title><content type='html'>&lt;P&gt;I have to confession to make. I am a build configuration / source control junkie. I don't know why or how it happened, but it all started long ago when I was at &lt;A title="U of W" href="http://www.math.uwaterloo.ca/"&gt;U of W&lt;/A&gt; and had coerced my way into getting access to code on some &lt;A title="ROM 2.4" href="http://www.hypercube.org/tess/rom/"&gt;ROM 2.4&lt;/A&gt; &lt;A title=MUD href="http://daedalmacabre.org/"&gt;MUD&lt;/A&gt;. (&lt;A title=MUD href="http://en.wikipedia.org/wiki/MUD"&gt;MUD&lt;/A&gt; = Mult-User Dungeon, and were text based precursors to today's &lt;A title=MMORPG href="http://www.43things.com/things/view/1173517"&gt;MMORPG&lt;/A&gt; ). I somehow got started on &lt;A title=RCS href="http://www.cs.purdue.edu/homes/trinkle/RCS/"&gt;RCS&lt;/A&gt;, I think this was from school. This lead to me implementing RCS and then &lt;A title=CVS href="http://www.nongnu.org/cvs/"&gt;CVS&lt;/A&gt; on our linux server for our MUD code. Suddenly coordination was so much easier! (Well of course). This then led to setting up cvsweb, and then figuring "make" to the n-th degree so that I had automated builds for both a staging and production environments and automated backups etc etc. &lt;/P&gt; &lt;P&gt; &lt;/P&gt; &lt;P&gt;Fast forward to the relative present at my current company I've lead us through three successive version control systems: from &lt;A title=CVS href="http://www.cvsnt.org/wiki"&gt;CVS&lt;/A&gt; to &lt;A title=Subversion href="http://subversion.tigris.org/"&gt;Subversion&lt;/A&gt; to now &lt;A title=TFS href="http://msdn2.microsoft.com/en-us/teamsystem/aa718934.aspx"&gt;TFS&lt;/A&gt;. Hopefully we can stick with TFS for the foreseeable future. TFS certainly has enough lever's and knobs to last a configuration junkie like me a good long while. &lt;/P&gt; &lt;P&gt; &lt;/P&gt; &lt;P&gt;So over the past two weeks I've attacked the TFS team build configuration for our web application. Previously we had setup a bare bones Team Build type that relied on a heavily extended Web Deployment Project to do all our custom work. Here's what I wanted: &lt;/P&gt; &lt;UL&gt; &lt;LI&gt;Build compiles all class libraries and runs code analysis on them &lt;/LI&gt; &lt;LI&gt;Build pre-compiles website &lt;/LI&gt; &lt;LI&gt;Turns debugging off in the web.config (somewhat negated by (re)discovering this ASP.NET feature) &lt;/LI&gt; &lt;LI&gt;Creates install package&lt;/LI&gt; &lt;UL&gt; &lt;LI&gt;The install is an automated process that &lt;/LI&gt; &lt;UL&gt; &lt;LI&gt;installs all required prerequsites (.NET Framework 2.0, ReportViewer, other 3rd party components etc) &lt;/LI&gt; &lt;LI&gt;restores database(s) &lt;/LI&gt; &lt;LI&gt;installs other machine wide configuration files &lt;/LI&gt; &lt;LI&gt;creates website(s), including deleting old one, making sure correct asp.net version is assigned, setting correct permissions &lt;/LI&gt; &lt;LI&gt;creates shortcut(s) &lt;/LI&gt;&lt;/UL&gt; &lt;LI&gt;To create the install involves &lt;/LI&gt; &lt;UL&gt; &lt;LI&gt;backing up all required databases&lt;/LI&gt; &lt;LI&gt;updating the web.config for install specific settings&lt;/LI&gt; &lt;LI&gt;packaging all the websites and prerequiste projects together in a self-extracting zip&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt; &lt;LI&gt;Deploy the project to the staging environment&lt;/LI&gt;&lt;/UL&gt; &lt;P&gt; &lt;/P&gt; &lt;P&gt; I've now refactored almost all of this functionality into a set of .targets files that I've deployed to the $(MSBuildExtensionsPath). This would then let me generate a Team Build Type for any of our website projects where the TFSBuild.proj file would look like the following:&lt;/P&gt; &lt;P&gt; &lt;FONT color=#0000ff&gt; &lt;/FONT&gt;&lt;/P&gt; &lt;P&gt;&amp;lt;?&lt;FONT color=#a31515 size=2&gt;xml&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;1.0&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;encoding&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;utf-8&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;?&amp;gt;&lt;/P&gt; &lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DefaultTargets&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;DesktopBuild&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;xmlns&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt; &lt;P&gt;   &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Import&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;$(MSBuildExtensionsPath)MyCompanyMyCompany.Buildv1.0MyCompany.TeamBuild.targets&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt; /&amp;gt;&lt;/P&gt; &lt;P&gt;   &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt; &lt;P&gt;      &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Reference&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;ProjectA&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Reference&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt; &lt;P&gt;   &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;PropertyGroup&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt; &lt;P&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;Project&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;/P&gt; &lt;P&gt; &lt;/P&gt; &lt;P&gt;&lt;FONT color=#000000&gt;I would only have to change the $(Reference) property and all the other Team Build properties could be derived from this. Great! I've got &lt;A title=DRY href="http://www.artima.com/intv/dry.html"&gt;DRY&lt;/A&gt; down, it looks well factored. I was happy. But then I started getting messages like these:&lt;/FONT&gt;&lt;/P&gt; &lt;P&gt; &lt;/P&gt; &lt;P&gt; Drop location is not defined in the Buld Type X&lt;/P&gt; &lt;P&gt; &lt;/P&gt; &lt;P&gt;And I knew the drop location was defined as when I did a Desktop Build I could get the value just fine. What was TFS's problem? Well I discovered that Team Build does NOT run your TFSBuild.proj through MSBuild. In fact, it uses XmlSerializer to parse the file. Which means the DropLocation and BuildDirectoryPath are not in fact evaluated as properties. Given this I don't understand why Microsoft did not just have them as other elements under the ProjectExtensions element. This would have been less misleading.&lt;/P&gt; &lt;P&gt; &lt;/P&gt; &lt;P&gt;Well that's the negative side of things. On the positive I wrote a SqlExecute MSBuild task I'm pretty happy with that I'll share here in another post. Also upcoming I should post about installations, and how we wrote our install script which is basically MSBuild and some ideas I have on that.&lt;/P&gt;
&lt;hr&gt;
&lt;b&gt;UPDATE:&lt;/b&gt; &lt;a href="http://blogs.msdn.com/buckh/default.aspx"&gt;Buck Hodges&lt;/a&gt; replied to my &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1211707&amp;SiteID=1&amp;mode=1"&gt;MSDN forum&lt;/A&gt; post and confirmed my findings. Also pointed at the &lt;a href="http://blogs.msdn.com/buckh/archive/2006/12/02/more-on-the-orcas-features-for-team-build.aspx"&gt;Orcas Team Build&lt;/a&gt; plans.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-6368251616381253900?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/6368251616381253900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2007/02/i-have-to-confession-to-make.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/6368251616381253900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/6368251616381253900'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2007/02/i-have-to-confession-to-make.html' title='MSBuild Bonanza (Part I)'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-6594457161068774224</id><published>2007-01-12T12:59:00.000-05:00</published><updated>2007-02-08T10:41:27.404-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>iPhone - The Honeymoon's over... already</title><content type='html'>&lt;p&gt;
  When I first saw the
  &lt;a href="http://www.apple.com/iphone/" title="iPhone"&gt;iPhone&lt;/a&gt; , I was
  really impressed, or perhaps a more accurate term in hindsight would be
  infatuated. It was very cool to get all these things into one device. I like
  having a mini-browser/email/phone all together in my blackberry.&amp;nbsp;Merging
  in the iPod&amp;nbsp;was great news.&amp;nbsp;But then I started getting the bad news:
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  &lt;strong&gt;Strike #1&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
  6 - 8 GB of memory. Plenty for anything&amp;nbsp;except for a media library,
  especially if you intend to store video. I hate having to choose what I want,
  which is why I have the 60 GB iPod video. Now this isn't such a big deal as
  8GB still leaves a lot of flexibility and it seems to work for all those Nano
  users.
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  &lt;strong&gt;Strike #2&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
  Price&amp;nbsp;-&amp;nbsp;$600&amp;nbsp;USD, which translates to
  &lt;a href="http://www.google.com/search?hl=en&amp;amp;lr=&amp;amp;rls=com.microsoft%3Aen-US&amp;amp;q=600+USD+in+CAD" title="706 CAD"&gt;706
  CAD&lt;/a&gt;. Can I trade in my iPod Video.. oh wait, not nearly the same memory,
  and likely not anyways.
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  &lt;strong&gt;Strike #3&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
  Found
  &lt;a href="http://weblogs.jupiterresearch.com/analysts/gartenberg/archives/2007/01/jobs_on_the_iph.html" target="blank_" title="this"&gt;this&lt;/a&gt;
  out today. I can't write software against it. I'll have this really cool, but
  closed device. Drive's me crazy.&amp;nbsp;So time to go look some more at the
  other options.
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  More coverage on
  &lt;a href="http://www.scripting.com/2007/01/12.html#whyShouldWeCheerForStevesPatents" title="Apple crappiness here"&gt;Apple
  crappiness here&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-6594457161068774224?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/6594457161068774224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2007/01/iphone-honeymoons-over-already.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/6594457161068774224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/6594457161068774224'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2007/01/iphone-honeymoons-over-already.html' title='iPhone - The Honeymoon&apos;s over... already'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-4926325847851735845</id><published>2007-01-11T16:21:00.000-05:00</published><updated>2007-02-08T10:36:18.979-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>ASP.NET Custom Control Properties</title><content type='html'>&lt;P class=western style="LINE-HEIGHT: 100%"&gt;&lt;SPAN lang=""&gt;&lt;FONT face=Arial size=2&gt;When authoring a custom ASP.NET   control, I believe it a best practice to store public properties in the   control's viewstate. This applies to both controls inheriting from WebControl   and to user controls. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt; &lt;P class=western lang="" style="LINE-HEIGHT: 100%"&gt; &lt;/P&gt; &lt;P class=western style="LINE-HEIGHT: 100%"&gt;&lt;FONT size=+0&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;SPAN lang=""&gt;In my many, many journeys with &lt;/SPAN&gt;&lt;FONT color=#0000ff&gt;&lt;U&gt;&lt;A href="http://www.aisto.com/roeder/dotnet/"&gt;&lt;SPAN&gt;&lt;SPAN&gt;Refelector&lt;/SPAN&gt;&lt;/A&gt;&lt;/U&gt;&lt;/FONT&gt;&lt;SPAN lang=""&gt; I've noticed a common pattern in the BCL which I've been now using for my public control properties: &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=+0&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt; &lt;P class=western style="LINE-HEIGHT: 100%"&gt;&lt;SPAN&gt;&lt;FONT size=+0&gt;
&lt;textarea name="code" class="c#" cols="60" rows="10"&gt;   
        [System.ComponentModel.DefaultValue("MyDefault")]
        public string MyProperty
        {
            get { return ViewState["MyProperty"] as string ?? "MyDefault"; }
            set { if (MyProperty != value) ViewState["MyProperty"] = value; }
        } 
&lt;/textarea&gt;   
&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt; &lt;P class=western style="LINE-HEIGHT: 100%"&gt; &lt;P class=western style="LINE-HEIGHT: 100%"&gt;&lt;FONT size=+0&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/P&gt; &lt;P class=western lang="" style="LINE-HEIGHT: 100%"&gt;&lt;FONT face=Arial size=2&gt;I've put together  a snippet for this which makes adding these properties (something I find myself frequently doing) much quicker.&lt;/FONT&gt;&lt;/P&gt; &lt;P class=western lang="" style="LINE-HEIGHT: 100%"&gt;  &lt;FONT size=+0&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt; &lt;P class=western lang="" style="LINE-HEIGHT: 100%"&gt;&lt;FONT face=Arial size=2&gt;The only thing to  remember when using the snippet is if ou use a value type (int, Decimal, etc)  you need to change the inner cast to use Nullable&lt;T&gt;, which is really easy in C#.  Just type a "?" mark as the snippet places the cursor right where you need it  when you finish. &lt;/FONT&gt;&lt;/P&gt; &lt;P class=western lang="" style="LINE-HEIGHT: 100%"&gt;  &lt;FONT face=Arial&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt; &lt;P style="LINE-HEIGHT: 100%"&gt;
&lt;textarea name="code" class="c#" cols="60" rows="10"&gt;   
        [System.ComponentModel.DefaultValue(42)]
        public int TheMeaningOfLife
        {
            get { return ViewState["TheMeaningOfLife"] as int? ?? 42; }
            set { if (TheMeaningOfLife != value) ViewState["TheMeaningOfLife"] = value; }
        }
&lt;/textarea&gt;
&lt;FONT face=Arial&gt;&lt;BR&gt;  &lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt; &lt;P class=western&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;SPAN lang=""&gt;You can download the snippet &lt;/SPAN&gt;&lt;FONT color=#0000ff&gt;&lt;U&gt;&lt;A href="http://thecodemonkey.net/propasp.zip"&gt;&lt;SPAN&gt;&lt;SPAN&gt;here&lt;/SPAN&gt;&lt;/A&gt;&lt;/U&gt;&lt;/FONT&gt;&lt;SPAN lang=""&gt;.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt; &lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-4926325847851735845?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/4926325847851735845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2007/01/when-authoring-custom-asp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/4926325847851735845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/4926325847851735845'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2007/01/when-authoring-custom-asp.html' title='ASP.NET Custom Control Properties'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-9107626949304473907</id><published>2007-01-11T14:34:00.000-05:00</published><updated>2007-02-08T10:42:07.407-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='humour'/><title type='text'>Database Maintenance Bible : The Book of Genesis</title><content type='html'>&lt;blockquote&gt;&lt;p&gt;In the beginning there was darkness in the database server and no backups to speak of therein.
&lt;/p&gt;&lt;p&gt;
And the great DBA spoke into the server and said "Let there be an Administration database" and so an Administration database was created.
&lt;/p&gt;&lt;p&gt;
Then the DBA spoke an said, "let the Administration database hold stored procedure code of varying types" and the stored procedures were created. The DBA looked at the stored procedures and said they were good.
&lt;/p&gt;&lt;p&gt;
Then the DBA said, "Let the stored procedures be called at distinct intervals and run so that knowledge is maintained". So 3 jobs were created and the DBA named them according to the knowledge they maintained, calling them System Backup, User DB Backup and Tlog Backups. And the DBA said it was good.
&lt;/p&gt;&lt;p&gt;
Then the DBA breathed life into the jobs and said "be fruitful and don't break dammit". And so they went and ensured the integrity of the server.
&lt;/p&gt;&lt;p&gt;
Then the DBA said, "let us keep several copies of the knowledge spanning 7 spins of the celestial globe known as "earth" in case the whole server goes to the shits". And so it was... and the DBA said it was very good.&lt;/p&gt;&lt;p&gt;- &lt;a href="http://www.linkedin.com/pub/1/130/56a"&gt;Sean Walker&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;
I asked graciously for a maintenance plan on our companies TFS server and this is what I received in response.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-9107626949304473907?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/9107626949304473907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2007/01/database-maintenance-bible-book-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/9107626949304473907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/9107626949304473907'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2007/01/database-maintenance-bible-book-of.html' title='Database Maintenance Bible : The Book of Genesis'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-116483292634250881</id><published>2006-11-29T15:37:00.000-05:00</published><updated>2006-11-29T15:45:35.090-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><title type='text'>WorkItemTrackingCacheRoot</title><content type='html'>In writing some web applications that access Team Foundation Server's work item tracking API I've run into permission issues as exceptions are thrown when trying to access the work item cache directory. This defaults to a directory in c:\documents and settings\&lt;username&gt;\local settings\&lt;etc&gt; .

&lt;a href="http://www.codeproject.com/useritems/TFS-WorkItemTracking-Web.asp"&gt;Some&lt;/a&gt; pages I've found recommend that you use a user with appropriate permissions. I would like to use the ASPNET user. And after some Reflector investigation discovered there is an appSetting called "WorkItemTrackingCacheRoot" that the TFS client object model uses to determine this directory. So you can override it in your application and TFS will use this.

&lt;blockquote&gt;
&lt;span style="font-family:courier new;"&gt;
&amp;lt;add key="&lt;b&gt;WorkItemTrackingCacheRoot&lt;/b&gt;" value="&lt;em&gt;your-absolute-directory-path&lt;/em&gt;" /&amp;gt;
&lt;/span&gt;
&lt;/blockquote&gt;

Use at your own risk!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-116483292634250881?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/116483292634250881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/11/workitemtrackingcacheroot.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/116483292634250881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/116483292634250881'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/11/workitemtrackingcacheroot.html' title='WorkItemTrackingCacheRoot'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-115457495517016741</id><published>2006-08-02T23:09:00.000-04:00</published><updated>2006-08-02T23:16:46.186-04:00</updated><title type='text'>Brain Explosions</title><content type='html'>So am working on putting together the process for the &lt;span style="font-weight: bold;"&gt;big project&lt;/span&gt;. Amalgamating experience and a dozen books and tens of articles on design, methodology, architecture and requirements is making my grey matter hurt... and occasiionally go on side tangents.

I'm also faced reently with a plethora of interviewing to do at work. Now here's a skill I need some more work on. Two non-verbal people who don't know each other are not prone to entering an easy dialogue. And technical assessment is hard of marginal cases. I think we just need better candidates.

But on to the &lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;crazy&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;idea&lt;/span&gt;of this post. I thought I might apply to some technical jobs to just see their interviewing style. Of course who's to say this would be of any value to me, as I've never been through what I thought was a particularly &lt;span style="font-weight: bold;"&gt;brilliant&lt;/span&gt; interview. Not to mention I'd be wasting said Acme Incorporated's time. Yes, not only crazy, but a stupid idea. No easy path to easy interviewing skills.

Back to book's and the school of hard knocks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-115457495517016741?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/115457495517016741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/08/brain-explosions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115457495517016741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115457495517016741'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/08/brain-explosions.html' title='Brain Explosions'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-115277525924406669</id><published>2006-07-13T05:45:00.000-04:00</published><updated>2006-07-13T22:16:38.700-04:00</updated><title type='text'>Rocketboomed</title><content type='html'>While trolling procrastination central I noticed a wired news article on &lt;a href="http://www.rocketboom.com"&gt;rocketboom&lt;/a&gt;. Intrigued I finally discovered this amazing vlog. Though the feeling I have now is much akin to discovering an amazing  book series, only to discover the author dead with no hope of finishing. Ahhh.. so now I'm satiating myself on the archives.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-115277525924406669?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/115277525924406669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/07/rocketboomed.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277525924406669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277525924406669'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/07/rocketboomed.html' title='Rocketboomed'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-115277521357525863</id><published>2006-07-11T00:14:00.000-04:00</published><updated>2006-07-13T03:20:13.576-04:00</updated><title type='text'>Billy Talent II</title><content type='html'>So I'm browsing around iTunes, because I don't want to/can't seem to focus on work this evening.. and happen upon &lt;A href="http://www.billytalent.com/"&gt;Billy Talent&lt;/A&gt; II in the top 10 of today's albums. &lt;BR&gt;&lt;BR&gt;It quickly brought to mind Jamal's rant on Billy Talent, and I do wish I could post it verbatim as a "&lt;A href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?id=160162763&amp;amp;s=143455"&gt;user review&lt;/A&gt;", because well, it was just so damn funny. Jamal is like having our own personal &lt;A href="http://www.imdb.com/name/nm0588222/"&gt;Dennis Miller&lt;/A&gt;. All I can recall was it involved him taking the album out and kicking it around the driveway for awhile. Looses something I guess in the translation.&lt;BR&gt;&lt;BR&gt;Personally, I liked the album, but yes, &lt;A href="http://www.billytalent.com/sections/gallery/large/32.jpg"&gt;the band&lt;/A&gt; does look like a complete collection of dorks. But I can not recall one time where i based my taste of music on the appearance of the musician.&lt;BR&gt;&lt;BR&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-115277521357525863?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/115277521357525863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/07/billy-talent-ii.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277521357525863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277521357525863'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/07/billy-talent-ii.html' title='Billy Talent II'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-115277517826158960</id><published>2006-06-23T12:03:00.000-04:00</published><updated>2006-07-13T03:19:38.263-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>SchemaImporterExtension = Giant Disaster</title><content type='html'>And I wondered why more people hadn't done this. SchemaImporterExtension sounds like a great idea at first. Let me define custom types for the xml deserialization process of a web service. &lt;BR&gt;I even managed to get it running without installing the library in the GAC and within the ASP.NET compilation model. Your milage may vary in a true environment as this was only on my development machine running Windows XP and IIS 5.1. A key requirement seemed to be having the assembly containing the SIE signed and the reference to it in web.config using the full assembly name reference (with publicKey etc.)&lt;BR&gt;So this was all working great, but I had the expectation that I could use the types I used on the server side on the client-side. No such luck, the whims of the xml deserializer foiled me at every turn. Types completely disappeared, especially the root type of return values. Types containing collections of types disappeared becoming ArrayOfBlahType. Argh. I'm sure there was some XmlAttribute magic and some type structure manipulation I could do to get everything working but it was well on it's way to being very clunky.&lt;BR&gt;Several hours later, I'm back to the much cleaner method of just letting wsdl proxy generator make up it's own types so I'm only "sharing schema, not types" across the service boundary. As both the service producer and consumer this is mildly frustrating.. but I hear Don Box should be happy.&lt;BR&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-115277517826158960?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/115277517826158960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/06/schemaimporterextension-giant-disaster.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277517826158960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277517826158960'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/06/schemaimporterextension-giant-disaster.html' title='SchemaImporterExtension = Giant Disaster'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-115277514364746417</id><published>2006-03-30T23:55:00.000-05:00</published><updated>2006-07-13T03:19:03.646-04:00</updated><title type='text'>Fickle Flickr</title><content type='html'>So, went over to the dark side today. That is, I signed up for a &lt;A href="http://www.flickr.com/photos/jkingry"&gt;flickr &lt;/A&gt;pro account to commemorate the &lt;A href="http://www.flickr.com/photos/jkingry/sets/72057594094670959/"&gt;Developer Challenge&lt;/A&gt; we had. Not abandoning &lt;A href="http://thecodemonkey.smugmug.com/gallery/1320042"&gt;smugmug&lt;/A&gt;, but flickr has a very different community to it. So we'll see how this goes.&lt;BR&gt;&lt;BR&gt;Their uploadr tool though doesn't like the JPEG images from my Pentax Option SV. &lt;SPAN style="FONT-WEIGHT: bold"&gt;Ergh.&lt;/SPAN&gt; Strike one against Flickr.&lt;BR&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-115277514364746417?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/115277514364746417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/03/fickle-flickr.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277514364746417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277514364746417'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/03/fickle-flickr.html' title='Fickle Flickr'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-115277509649957545</id><published>2006-03-22T01:46:00.000-05:00</published><updated>2006-07-13T03:18:16.500-04:00</updated><title type='text'>Writing Documentation is no fun</title><content type='html'>Perhaps I am spoiled in that I can call the majority of what I do for a living "fun". I throughly enjoy the work I do and find it challenging. I count myself lucky every day for this.
But writing documentation is not something I think I'm good at, and I think from this stems the non-funness factor. In fact when faced with such a task, every &lt;a href="http://www.43things.com/things/view/225"&gt;procrastination&lt;/a&gt; tool at my disposal comes out, hence.. blogging a last resort. Well I should stop &lt;a href="http://www.43things.com/things/view/225"&gt;procrastinating&lt;/a&gt; and get back to specification writing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-115277509649957545?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/115277509649957545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/03/writing-documentation-is-no-fun.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277509649957545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277509649957545'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/03/writing-documentation-is-no-fun.html' title='Writing Documentation is no fun'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-31058042.post-115277502937324017</id><published>2006-03-18T17:51:00.000-05:00</published><updated>2006-07-13T03:17:09.373-04:00</updated><title type='text'>A new beginning (again!)</title><content type='html'>Well here's a temporary start to a blog... for now anyways. If I ever get &lt;a href="http://thecodemonkey.net/"&gt;my page&lt;/a&gt; up and running again I guess I'll have to move back there. Having some trouble with &lt;a href="http://communityserver.org/"&gt;Community Server&lt;/a&gt;, need to &lt;a href="http://communityserver.org/forums/thread/520960.aspx"&gt;recompile&lt;/a&gt; it I guess...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/31058042-115277502937324017?l=thecodemonkey.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodemonkey.blogspot.com/feeds/115277502937324017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://thecodemonkey.blogspot.com/2006/03/new-beginning-again.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277502937324017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/31058042/posts/default/115277502937324017'/><link rel='alternate' type='text/html' href='http://thecodemonkey.blogspot.com/2006/03/new-beginning-again.html' title='A new beginning (again!)'/><author><name>Joe</name><uri>http://www.blogger.com/profile/02165367573326877410</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
