<?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-282487425534208111</id><updated>2012-02-02T09:17:11.822-06:00</updated><category term='C#'/><category term='SQL Server 2005'/><category term='Development'/><category term='Mono'/><category term='Architecture'/><category term='VB'/><category term='Linq'/><category term='Unit Testing'/><category term='temporary tables'/><category term='Web'/><category term='.Net'/><title type='text'>Vampire Basic</title><subtitle type='html'>Code that hides in the dark, then bites.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-282487425534208111.post-5819372893131196718</id><published>2010-06-18T09:45:00.001-05:00</published><updated>2010-06-18T09:46:04.876-05:00</updated><title type='text'>Running Mercurial on Windows Without CGI</title><content type='html'>In the past, the only real way to run python apps in IIS has been through CGI. FastCGI doesn't work because of an implementation flaw in Python 2.x script libraries that basically prevents FastCGI from functioning on Windows (supposedly this is fixed in Python 3.x).  ISAPI wasn't really an option, either, since there was not really a good enough implementation of the WSGI server interface standard for IIS.&lt;br /&gt;&lt;br /&gt;By the way, for those of you who haven't been keeping up with the inner workings of Python (that would be most of us Windows folks), WSGI (Web Server Gateway Interface) is a Python standard defined in &lt;a href="http://www.python.org/dev/peps/pep-0333/"&gt;PEP 333&lt;/a&gt; (PEP is an acronym for Python Enhancement Proposals). It details how Python web applications/Python web frameworks should interface with web servers.&lt;br /&gt;&lt;br /&gt;Things have change a little in the months since I wrote my &lt;a href="http://vampirebasic.blogspot.com/2009/06/running-mercurial-on-windows.html"&gt;original post&lt;/a&gt; on running Mercurial on Windows. &lt;a href="http://hex-dump.blogspot.com"&gt;Someone&lt;/a&gt; who has a great deal of dedication has been working on a WSGI interface for IIS since before my last post, and has now gotten it to a point where it works marvelously with Mercurial.  Thanks to Jason R. Coombs and his team for all their hard work on the &lt;a href="http://code.google.com/p/isapi-wsgi/"&gt;isapi-wsgi&lt;/a&gt; project. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;On with the show&lt;/h2&gt;&lt;br /&gt;Installing Mercurial as a server using isapi-wsgi is SO much easier than fiddling with CGI that it was actually a joy.  These instructions assume Mercurial 1.5.1.  Keep in mind that since you don't have anything on Windows as cool as the &lt;a href="http://www.freebsd.org/ports/"&gt;FreeBSD Ports and Packages Collection&lt;/a&gt; to build stuff and manage dependencies for you that you will have to make sure you match the version of Mercurial to the correct version of Python yourself. IIS needs to be already installed and functioning.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Install the Python 2.5.6 &lt;a href="http://www.python.org/download/"&gt;binary installer package&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Install the latest of Mark Hammond's indispensable &lt;a href="http://sourceforge.net/projects/pywin32/"&gt;Python for Windows package&lt;/a&gt;, for Python 2.6 .&lt;/li&gt;&lt;li&gt;Install the binary package for isapi-wsgi. &lt;a href="http://code.google.com/p/isapi-wsgi/downloads/list"&gt;0.4.2&lt;/a&gt; is the one that you want, since it now supports SSL properly. isapi_wsgi.py will be installed in the 'site-packages' directory of your Python installation...assuming you take the defaults.  You should take the defaults.&lt;/li&gt;&lt;li&gt;Go &lt;a href="http://code.google.com/p/isapi-wsgi/wiki/InstallationInstructions"&gt;here&lt;/a&gt; and follow the instructions in the Testing section to make sure you didn't mess it up.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Go to &lt;a href="http://mercurial.selenic.com/downloads/"&gt;Selenic&lt;/a&gt; and download the source code for Mercurial.  Its in a tarball, so you'll probably want to install &lt;a href="http://www.7-zip.org/download.html"&gt;7-Zip&lt;/a&gt; at this point, because Microsoft obstinately refuses to include tar and gzip support directly in the Windows Explorer...and really why should they since 7-Zip is free, and does exactly that.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Once you've extracted this thing somewhere (or not, you can navigate the archive in 7-Zip and drag-drop the file we need out), find the contrib\win32 directory. Copy hgwebdir_wsgi.py to a directory from which you want to serve Mercurial.  I chose C:\inetpub\wwwroot\hg.  It doesn't have to be in inetpub, you could use a virtual directory.  Don't put your Mercurial repositories in this directory.  You'll confuse Mercurial.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;On IIS 6 and above, create a new App pool for your Mercurial directory if your IIS installation is doing ANYTHING other than Mercurial.  Make sure you make your Mercurial directory into a Application in IIS, and ensure the Application is assigned to the App pool you created for Mercurial.  In IIS 5.1, you may want to set the Application Isolation as High "(Isolated)".  I mean, the Python interpreter is native code. It could crash and take your entire IIS process down with it. You probably don't want that.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Edit your copy of hgwebdir_wsgi.py.  Make the top of it look kinda like this:&lt;br /&gt;&lt;pre&gt;# Configuration file location&lt;br /&gt;hgweb_config = r'c:\inetpub\wwwroot\hg\hgweb.config'&lt;br /&gt;&lt;br /&gt;# Global settings for IIS path translation&lt;br /&gt;path_strip = 0   # Strip this many path elements off (when using url rewrite)&lt;br /&gt;path_prefix = 1  # This many path elements are prefixes (depends on the&lt;br /&gt;                 # virtual path of the IIS application).&lt;br /&gt;&lt;/pre&gt;hgweb_config is pretty simple, it tells the script where to find its config file. path_prefix should be 0 if hgwebdir_wsgi.py is in the root of the web, 1 if its one directory down (server/hg), 2 if you get to it by server/directory/hg... you should get the idea. I don't know what path_strip does, but it sounds risque, so I didn't mess with it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Run the hgwebdir_wsgi.py script &lt;pre&gt;python hgwebdir_wsgi.py&lt;/pre&gt;to make a shim dll for Mercurial. All this really does is copy a file from the Python Win32 Extensions package to where the script resides and names it appropriately. Which is nice because you don't have to figure it out for yourself.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Create your hgweb.config file. This is all mine has in it.&lt;br /&gt;&lt;pre&gt;[paths]&lt;br /&gt;/ = c:\repos\*&lt;/pre&gt;If you read my last post, then yes, there is just one star this time.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Create an ISAPI script mapping to the shim dll that the script generated. In IIS 5, you just create a script mapping to the dll using .* as the extension (clear the check box that says "Check that files exist", or IIS will generate hate messages). In IIS 6 and above, you will want to create a wildcard script map to that shim dll.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Create a test repository in c:\repos\ (or where ever).  If it shows up in the list on http://server/hg, have you a cold one. Good job.  If it doesn't, you may have messed up your hgweb.config, maybe your permissions on c:\repos\. Remember, the identity that IIS (or the IIS worker pool) is running under will need full control access to your repository directory.  If you don't see anything at all (or 401's and 404's and bears, oh my!), you may have messed up your script map in IIS or the editing the hgwebdir_isapi.py script.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;SSL and web security both worked well through IIS.  One thing to keep in mind is that the Hg client doesn't care a thing about Windows Integrated Security, so if you want to secure your repos, you'll have to use SSL+Basic Authentication.&lt;br /&gt;&lt;br /&gt;If you find yourself having to diagnose your setup, iisreset is your friend. Because you're loading things into the IIS process space, and IIS isn't very likely to reload things just because you changed them, you may find that you have to restart it when you make certain configuration changes.&lt;br /&gt;&lt;br /&gt;I found setting up Mercurial with isapi-wsgi to be easier than with CGI. It seems snappier, and less fussy about certain operations that I had trouble with in CGI.  I imagine if FastCGI were to ever work with Python on Windows, it would actually perform better than ISAPI, due to the nature of threading within the Python interpreter, but for now, we already have something better than CGI, so that's what I'll stick with.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Issues I've seen&lt;/h2&gt;On a 64 bit Windows 2008 R2 server, I ran into a bit of trouble with Mercurial not being able to find its binary bits.  See Mercurial has some modules in it that were written in C, because they're really hard core and mathy and they needed some extra speed to make Mercurial as fast as it really should be.  In order to fix the "unable to locate module" business, I downloaded the Mercurial source, and lo, the authors had written pure Python versions of the C modules that were giving me grief.  I tossed the pure python modules on the PYTHONPATH, and everything worked just fine.&lt;br /&gt;&lt;br /&gt;I'm going to research this particular issue again, because I've learned a little more about how Python loads C code.  It sure would be nice to know how to get Mercurial running at full tilt in IIS 7.5.&lt;br /&gt;&lt;br /&gt;&lt;center&gt; &lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2010/06/running-mercurial-on-windows-without.html';reddit_title='Running Mercurial on Windows Without CGI';digg_url='http://vampirebasic.blogspot.com/2010/06/running-mercurial-on-windows-without.html';digg_title='Running Mercurial on Windows Without CGI';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt; &lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt; &lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-5819372893131196718?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/5819372893131196718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2010/06/running-mercurial-on-windows-without.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/5819372893131196718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/5819372893131196718'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2010/06/running-mercurial-on-windows-without.html' title='Running Mercurial on Windows Without CGI'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-487380165817076479</id><published>2010-04-20T11:06:00.001-05:00</published><updated>2010-04-20T11:07:37.370-05:00</updated><title type='text'>How to debug an ISAPI Extension with Visual C++ 2010 Express on Windows XP</title><content type='html'>I had a great deal of trouble figuring out how to debug an ISAPI extension I'm writing, and unfortunately, most of the information on the internet about ISAPI has gotten a little stale since the advent of .Net for web development.&lt;br /&gt;&lt;br /&gt;On Windows, native code is moving further into the realm of witchcraft. Because witchcraft is scary, the Visual Studio team hid all the powerful witchery in 2010 C++ Express Edition. To turn all the really useful stuff back on, you have to go to Tools &amp;gt; Settings and select "Advanced Settings". Now you can get at the "Attach to process..." feature.&lt;br /&gt;&lt;br /&gt;That wasn't what hung me up.  I followed the &lt;a href="http://msdn.microsoft.com/en-us/library/ms525937(VS.90).aspx"&gt;instructions&lt;/a&gt; in the MSDN library, which basically say "Attach debugger to Inetinfo.exe, enjoy."  But I got no joy.  I got "The breakpoint will not currently be hit. No symbols have been loaded for this document." in the interactive debugger.&lt;br /&gt;&lt;br /&gt;So, I enabled symbol download in Visual C++ by navigating through Debug &amp;gt; Options and Settings... and clicked on Symbols in the tree view on the left.  Check the box next to Microsoft Symbol Servers, created a folder to hold whatever it downloads and put that path in the Cache symbols in this directory: box, and I was ready to go.  Except it didn't help me out.&lt;br /&gt;&lt;br /&gt;I loaded the Windows SDK, I loaded the Debugging Tools for Windows (which are inconveniently in a 650mb iso with the Windows DDK), I installed depends.exe (which apparently does not come with the Windows SDK anymore), I installed SysInternals ProcMon.exe.  Of all the hundreds of megabytes of junk I downloaded and installed, none of the tools told me what I needed to know.&lt;br /&gt;&lt;br /&gt;I'll save you the effort of installing all that stuff and just tell you that you need to put your IIS Applications into Application Protection: Low(IIS Process).  If you don't, the ISAPI dll you are trying to debug gets loaded into some dllhost.exe process. If you leave the IIS Application set to Medium(Pooled) or High(Isolated), you will have to attach your debugger to one of the dllhost.exe processes. It is harder to figure out which dllhost.exe to attach the debugger to, so set it Application Protection to Low, THEN follow the instructions on the MSDN Library.&lt;br /&gt;&lt;br /&gt;So, long story short, I was attaching the debugger to the wrong process.  And you can't debug code that isn't loaded into memory.  It seems a shame that that is the case, because if it weren't, then native code really would be witchcraft.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2010/04/how-to-debug-isapi-extension-with.html';reddit_title='How to debug an ISAPI Extension with Visual C++ 2010 Express on Windows XP';digg_url='http://vampirebasic.blogspot.com/2010/04/how-to-debug-isapi-extension-with.html';digg_title='How to debug an ISAPI Extension with Visual C++ 2010 Express on Windows XP';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-487380165817076479?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/487380165817076479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2010/04/how-to-debug-isapi-extension-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/487380165817076479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/487380165817076479'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2010/04/how-to-debug-isapi-extension-with.html' title='How to debug an ISAPI Extension with Visual C++ 2010 Express on Windows XP'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-3172085451814982027</id><published>2009-06-07T10:53:00.035-05:00</published><updated>2009-06-14T11:04:48.441-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><title type='text'>Running Mercurial on Windows</title><content type='html'>&lt;p&gt;Mercurial, if you haven't played with it yet, is one of the easiest, fastest source control mechanisms to hit Windows in recent years.  If you have heard of Mercurial (or Hg, as some folks will type it, the symbol on the &lt;a href="http://en.wikipedia.org/wiki/Periodic_table"&gt;periodic table of elements&lt;/a&gt; for &lt;a href="http://en.wikipedia.org/wiki/Mercury_%28element%29"&gt;mercury&lt;/a&gt;), you may think I misspoke with that "Windows" bit, since only those long-haired open source hippie Linux people use that freebie distributed version control.  Not true!  As a matter of fact, for your own personal projects, Hg is probably one of the easiest, fasted version control mechanisms you can use for local-only development.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Getting started&lt;/h4&gt;The basic reference material you will need for Hg is available in the Mercurial wiki at &lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;http://www.selenic.com/mercurial/wiki/&lt;/a&gt;. Just so you don't have to read it, I'll continue below.&lt;br /&gt;&lt;p&gt;On your local Windows box, you will want to install &lt;a href="http://bitbucket.org/tortoisehg/stable/wiki/Home"&gt;TortoiseHg&lt;/a&gt;. If anybody has ever used the fine TortoiseSVN on Windows, you will be immediately familiar with the direct Windows Explorer integration with source control.  Some of the more recent versions of TortoiseHg (0.7.6 is the latest as of this writing) include a full installation of the command-line version of Mercurial, saving Windows uses the hassle of finding and running another installer.  You will eventually come up with a need for the command-line version of Hg, and you will want to become familiar with its simple commands anyway.&lt;br /&gt;&lt;br /&gt;For Visual Studio users (Standard edition and above, sorry Express edition users. Out in the cold as usual.), you can install &lt;a href="http://sharesource.org/project/visualhg/"&gt;VisualHg&lt;/a&gt; to get that sweet, sweet development environment integration that the users of Visual Source Safe and TFS currently enjoy in their development experience.  Once installed, you can enable the source control integration within Visual Studio by going to Tools-&gt;Options, then choosing "Source Control" in the tree view, and changing the "Current source control plug-in:" combo box.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As a side note, if you're still using VSS...please stop. SVN and Mercurial are, at the very least free, and are far less likely to corrupt your source repository. Also, if you aren't paying for &lt;a href="http://msdn.microsoft.com/en-us/library/ms181049%28VS.80%29.aspx"&gt;each and every seat license&lt;/a&gt; of VSS (even if you put it on a server and share it), you're stealing from MS at the rate of about &lt;a href="http://www.cdw.com/shop/products/default.aspx?edc=887257"&gt;$390&lt;/a&gt; a seat. Don't place your business and your code at risk by using VSS.&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Beyond local development&lt;/h4&gt;&lt;br /&gt;Despite what some other &lt;a href="http://www.brycobat.net/2008/07/09/serving-mercurial-from-windows-part-0/"&gt;ill-informed (yet admittedly old) blogs&lt;/a&gt; have implied, Mercurial &lt;i&gt;can&lt;/i&gt; be hosted in IIS on Windows. Nobody's set out step-by-step instructions all in one place, but that is about to change.&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;For all versions of Windows&lt;/h4&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Install Mercurial 1.2.1 on the server.  The version that comes with TortoiseHg is not sufficient, it will not drive the CGI application.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Install Python 2.5.4 on your server. Mercurial 1.2.1 components are compiled against that version of Python. Any other version of Python will cause a "Bad Magic Number" error on the server.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a directory &lt;i&gt;somewhere&lt;/i&gt; to hold the Mercurial source tree. Open a cmd window and navigate to whichever directory you want this source tree to be contained within, then type in&lt;br /&gt;&lt;pre&gt;hg clone http://selenic.com/repo/hg&lt;/pre&gt; (robbed from &lt;a href="http://stackoverflow.com/questions/818571/how-to-setup-mercurial-and-hgwebdir-on-iis"&gt;Stack Overflow&lt;/a&gt;).  This command will create a directory named hg, then download all the code in the Mercurial source repository into the hg directory. What we're after here is is the hgwebdir.cgi file, which is...a Common Gateway Interface app. Duh. And I'll bet you thought that cgi was dead.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a directory on the file system (separate from any other web app files you have on your web server) to map in as a Virtual Directory in IIS. I used C:\inetpub\hgcgi\.  Make sure this directory has read access in NTFS for the service account IIS (or your IIS app pool for Vista, XP x86-64, Server 03 and Server 08) is running under.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Copy the hgwebdir.cgi file into your virtual-directory-to-be.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You also want to extract the contents of the Library.zip file contained in your Mercurial installation directory to your virtual-directory-to-be.  If you installed TortoiseHg 0.7.6, you will find this within the TortoiseHg installation directory.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Copy the entire "templates" directory from the Mercurial installation directory to a "templates" directory within the virtual-directory-to-be.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a file named hgweb.config.  This is absolutely nothing like an Asp.Net web.config.  Its more like an ini file from the days of old. And you have to actually add text to it. You want something that looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[paths]&lt;br /&gt;MySourceCode = C:\Repositories\**&lt;br /&gt;[web]&lt;br /&gt;style = monoblue&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The [paths] segment is in the form &lt;virtual directory&gt; = local path. You can list out repository locations manually, or you can do as above, and have it take all of the repos in a location.  And yes, the ** is correct.  Most of the other documentation around the web is unix-style fs specific, and suggest using the [collections] section as opposed to the [paths] section, but don't be surprised when it doesn't work on Windows.  I never had any luck with using the [collections] section.&lt;br /&gt;And yeah, you want to change the style.  Because you can.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Once you get your repos to show up in the Mercurial cgi script, you can go into the repo's .hg directory, find the hgrc file therein and configure it.  The syntax is the same as hgweb.config, and it allows you to set settings for the repository itself. Such as the style.  Because you can. Details on the config file are &lt;a href="http://linux.die.net/man/5/hgrc"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;That's everything you must do that is common to all versions of Windows.&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;IIS 7 (Windows Vista, Server 08)&lt;/h4&gt;Just like everything else that is related to Vista, Microsoft changed the whole UI for the IIS Manager. This is good, because IIS Manager (just like the Component Services snap-in) in Server 2003 is a fussy, buggy, expletive-inducing wreck. IIS 7 does give you the ability to install Asp.Net "filters" (called a "Managed Handler" in IIS Parlance, called an HttpHandler in Asp.Net parlance) directly into IIS. Kinda cool really, since writing ISAPI filters requires that icky native code that seems to bamboozle so many people. Maybe someone will write a nice Managed Handler for Mercurial in the future, but for now, we have to use CGI.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Install IIS.  In Vista, its Control Panel-&gt;Programs and Features in "Classic View" or Control Panel-&gt;Programs in the new Vista view. Click on "Turn Windows features on or off." Expand "Internet Information Services", then select "Web Managment Tools" to install IIS Management Console.  Select "World Wide Web Services", then expand "World Wide Web Services", then expand "Application Development Features" and make sure "CGI" is selected.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add your virtual directory for Mercurial.  That's the one that has hgwebdir.cgi in it. Right click a web site (I just mapped it into the "Default Web Site", but any will do.), and choose "Add application" You could "Add virtual directory" and then upgrade the virtual directory to an application, but the virtual directory mapping has to be an "application." In the dialog, I set the alias to hg and the Physical path to "C:\inetpub\hgcgi". There is a nice "Test settings..." button here that will help you determine if your application directory is configured property.  I never did get my authorization warning to go away, even though the CGI script would run.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Map in the Python interpreter as a script engine.  Click on your new application/virtual directory.  In the center pane, double-click "Handler Mappings." Normally, if you wanted to execute Python scripts on the server, you would map the interpreter to *.py.  But we're running a cgi app through the python interpreter. Click on "Add Script Map..." and put in *.cgi for the Request Path.  Put &lt;pre&gt;C:\Python25\python.exe -u %s %s&lt;/pre&gt; in for Executable.  Give your mapping a name.  I used Python 2.5.  The %s %s mess above are substitution symbols (like printf(), or string.Format()) for arguments passed to the python interpreter that tell it what script it is executing on behalf of IIS.  After that, click the "Request Restrictions..." button, and choose the "Access" tab. Pick the "Execute" option, so you can "Execute" the cgi application. Click OK to save. A dialog will pop up that says "Do you want to enable this ISAPI application?", which is a bit bizarre since you are enabling a CGI application, but you should say Yes.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Enable the script engine for your application/virtual directory.  Right click your new "Python 2.5" handler mapping, and select "Edit feature permissions...", and make sure all of the checkboxes there are checked.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h4&gt;Windows Server 2003/XP&lt;/h4&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Buy Server 2008.  I hear that if you get it on subscription, you get free upgrades. If you can't talk your boss into paying for the next scheduled maintenance on Balmer's &lt;a href="http://www.astonmartin.com/eng/thecars/v12vantage-2"&gt;V12 Vantage&lt;/a&gt; (and if he doesn't really have one, he probably should), make sure IIS is installed on the Server. Control Panel-&gt;Add or Remove Programs, then Add/Remove Windows Components.  Select Application Server, and you should be set.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add your virtual directory for Mercurial.  That's the one that has hgwebdir.cgi in it. Right click a web site (I just mapped it into the "Default Web Site", but any will do), and choose New-&gt;Virtual Directory. In the dialog, I set the alias to hg and the Physical path to "C:\inetpub\hgcgi". By default, in Server 03, virtual directories are mapped in as "Web Applications," but if it isn't set up that way, you can right click the virtual directory, and click the "Home Directory" tab.  On the bottom of that tab, in the "Application settings" section, there should be a button labeled "Add."  Once you click it, the virtual directory becomes a "Web Application."  Also, while you're there, make sure the "Execute permissions:" drop down says "Execute."&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Map python in as the cgi script handler.  Do this by right clicking the virtual directory, then selecting the "Home Directory" tab.  In the "Application settings" section, click the "Configuration" button. On the "Mappings" tab, click the "Add..." button.  For "Executable", put in the following:&lt;br /&gt;&lt;pre&gt;C:\Python25\python.exe -u "%s %s"&lt;/pre&gt; And make sure you put the double quotes in exactly as shown. This is because IIS Manager is and won't take it without them.  In "Extension", put ".cgi".  Clear the checkbox that says "Verify that file exists", set the checkbox that says "Script engine."&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Enable Python as Web Service Extension (Server 03/XP x64). In IIS Manager, right-click the Web Service Extension to "Add a new Web service extension...". You can name the extension anything you want, I chose "Python 2.5". Click the "Add..." button.  In "Path to file", put C:\Python25\python.exe -u "%s %s". It must exactly match the ".cgi" mapping on your virtual directory, or it won't work. Check "Set extension status to Allowed".&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;Point your browser to http://server/HgVDir/hgwebdir.cgi/ and enjoy.  You should now be able to use Mercurial against that virtual directory.  To secure your source control repository, you should set up SSL on your server, and mark your hg virtual directory to require SSL.  Then set the virtual directory to use Basic security, as this is what the hg client tools support.  Basic-over-SSL is pretty secure, since the SSL encrypted connection is established well before the Basic security credential exchange takes place.&lt;br /&gt;&lt;br /&gt;To create new repos on the server, you'll want to clone them to the server from your workstation machine.  The easiest way to do this is to hg serve from your workstation, then log onto the server and pull your new repo into the right place on the server from your workstation.  After that, go into .hg in your server-side repo and configure your hgrc file.  Once that is complete, you can synchronize your server repo with your workstation repo any time you wish.&lt;br /&gt;&lt;br /&gt;And just in case you're wondering, the -u switch on the python interpreter places the interpreter in "unbuffered" mode, so results are sent to IIS immediately with no delay. Supposedly, for CGI, it improves performance.&lt;br /&gt;&lt;br /&gt;Give hg a shot. Its effective and I've had quite a bit of success with it.  Maybe you'll like it, too.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/06/running-mercurial-on-windows.html';reddit_title='Running Mercurial on Windows';digg_url='http://vampirebasic.blogspot.com/2009/06/running-mercurial-on-windows.html';digg_title='Running Mercurial on Windows';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-3172085451814982027?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/3172085451814982027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/06/running-mercurial-on-windows.html#comment-form' title='32 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3172085451814982027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3172085451814982027'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/06/running-mercurial-on-windows.html' title='Running Mercurial on Windows'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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>32</thr:total></entry><entry><id>tag:blogger.com,1999:blog-282487425534208111.post-857871922936792586</id><published>2009-05-30T16:05:00.007-05:00</published><updated>2009-05-30T18:46:32.698-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>Connection per request with Ado.Net</title><content type='html'>Say you have a service layer component that has reference to a DAL component. Say that the service layer calls two different methods on the DAL component, and that those methods need to be bound in one single transaction.  How do you achieve this within the confines of a web application?&lt;br /&gt;&lt;br /&gt;Since transactions are the domain of the service layer (business logic components...whatever), this should be pretty easy, right?  Just start a transaction one way or another, call your methods, commit/rollback, and move right along. The devil is really in the details on this, however.&lt;br /&gt;&lt;br /&gt;For the sake of this discussion, pretend that this code exists in the system:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;'Highly Contrived Example&lt;br /&gt;Public Class Stuff&lt;br /&gt;    Dim _Id As Long&lt;br /&gt;    Public Property Id As Long&lt;br /&gt;        Get()&lt;br /&gt;            Return _Id&lt;br /&gt;        End Get&lt;br /&gt;        Set(value As Long)&lt;br /&gt;            _Id = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Dim _Thingy As Thingy&lt;br /&gt;    Public Property Thingy As Thingy&lt;br /&gt;        Get()&lt;br /&gt;            Return _Thingy&lt;br /&gt;        End Get&lt;br /&gt;        Set(value as Thingy)&lt;br /&gt;           _Thingy = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;Public Class Thingy&lt;br /&gt;   ...Whatever goes here&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;Public Class DaoBase&lt;br /&gt;    Dim _Connection As IDbConnection&lt;br /&gt;    Public Property Connection As IDbConnection&lt;br /&gt;        Get()&lt;br /&gt;            Return _Connection&lt;br /&gt;        End Get&lt;br /&gt;        Set(Connection As IDbConnection)&lt;br /&gt;            _Connection = Connection&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;'This is a terribly designed component&lt;br /&gt;Public Interface IDAO&lt;br /&gt;    Function SaveStuff(arg As Stuff) As Stuff&lt;br /&gt;    Sub UpdateThingyOnStuff(arg As Stuff)&lt;br /&gt;End Interface&lt;br /&gt;&lt;br /&gt;Public Class ServiceComponent&lt;br /&gt;    Dim _DAO As IDAO&lt;br /&gt;    Public Property DAO As IDAO&lt;br /&gt;        Get()&lt;br /&gt;            Return _DAO&lt;br /&gt;        End Get&lt;br /&gt;        Set(value As IDAO)&lt;br /&gt;            _DAO = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public Sub DoSomethingCool(ByVal someStuff As Stuff)&lt;br /&gt;        Using txn As New System.Transactions.TransactionScope&lt;br /&gt;            someStuff = DAO.SaveStuff(someStuff)&lt;br /&gt;            DAO.UpdateThingyOnStuff(someStuff)&lt;br /&gt;&lt;br /&gt;            txn.Complete&lt;br /&gt;        End Using&lt;br /&gt;    End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I will be discussing the implementation of the IDAO interface.&lt;br /&gt;&lt;br /&gt;In a web app, you don't really have any state between requests, except that which you can stuff into Session or stuff into a cookie.  You can't really place a database connection object into Session. Well, you can, but when you have to switch from in-memory Session to, say SQL Session state, you're screwed.  Nevermind having to figure out what to do about fixing the connection if it breaks down on you.  And it scales like crap, too, because sessions may take a long time to become "abandoned" as far a the server is concerned, so you end up with database connections being held open that are idle.&lt;br /&gt;&lt;br /&gt;You surely can't cram a connection object into a cookie, so that means that you have to open and close database connections &lt;i&gt;within&lt;/i&gt; the scope of a single web request.&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;The wrong way&lt;/h5&gt;&lt;br /&gt;AKA, the way I used to do it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Imports System.Data.SqlClient&lt;br /&gt;&lt;br /&gt;Public Class DAO&lt;br /&gt;    Implements IDAO&lt;br /&gt;&lt;br /&gt;    Public Function SaveStuff(arg As Stuff) As Stuff&lt;br /&gt;        Using conn = New SqlConnection&lt;br /&gt;            conn.Open&lt;br /&gt;&lt;br /&gt;            Dim cmd = new SqlCommand&lt;br /&gt;            'Setup the command object here&lt;br /&gt;&lt;br /&gt;            cmd.ExecuteNonQuery&lt;br /&gt;        End Using&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    Public Sub UpdateThingyOnStuff(arg As Stuff)&lt;br /&gt;        Using conn = New SqlConnection&lt;br /&gt;            conn.Open&lt;br /&gt;&lt;br /&gt;            Dim cmd = new SqlCommand&lt;br /&gt;            'Setup the command object here&lt;br /&gt;&lt;br /&gt;            cmd.ExecuteNonQuery&lt;br /&gt;        End Using&lt;br /&gt;    End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The problem with this DAL is that the connection doesn't stay open during the transaction.  Using System.Transactions as I have done here, the ambient transaction elevates to a Distributed Transaction when you open the new connection in the second DAL call.  This means you have to actually enable and configure the MSDTC, and it degrades performance.&lt;br /&gt;&lt;br /&gt;If you use ADO.Net transactions instead of System.Transactions, you still have the same problem, except that you now have to keep up with a transaction object. With ADO.Net transactions, you could be creative and retain the connection when you pass in a transaction object, but you still have to come up with some strategy to close the connection when your transaction ends.  You could place a Close() method on your DAL components that your service layer components could call, but it just seems so...hacky.&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;The right way&lt;/h5&gt;&lt;br /&gt;Open your database connection at the beginning of your web request and close it at the end.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;...inside global.asax&lt;br /&gt;&lt;br /&gt;Protected Sub Application_BeginRequest(sender As Object, e As EventArgs)&lt;br /&gt;    'Database vendor-agnostic code.&lt;br /&gt;    Dim connectionString = System.Configuration.ConfigurationManager.ConnectionStrings("sampleDbConnString")&lt;br /&gt;    Dim provider = System.Data.Common.DbProviderFactories.GetProvider(connectionString.Provider)&lt;br /&gt;    Dim connection = provider.CreateConnection&lt;br /&gt;&lt;br /&gt;    connection.Open&lt;br /&gt;&lt;br /&gt;    'The Context.Items collection is a per-request information store.&lt;br /&gt;    Context.Items("DbConnection") = connection&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Protected Sub Application_EndRequest(sender As Object, e As EventArgs)&lt;br /&gt;    Dim connection = DirectCast(Context.Items("DbConnection"), System.Data.IDbConnection)&lt;br /&gt;&lt;br /&gt;    If connection IsNot Nothing Then connection.Close&lt;br /&gt;End Sub&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Doing the above leaves only the question of how to get reference to the connection into the DAL components.  Since you end up having to construct your DAL components at some point anyway (say, Page_Load), you could simply fetch the connection object off the Context.Items collection and place it on the DAL component.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;...in Page_Load somewhere...&lt;br /&gt;me.Service = New ServiceComponent&lt;br /&gt;me.Service.DAO = New DAO&lt;br /&gt;me.Service.DAO.Connection = Context.Items("DbConnection")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This gets you out of DTC elevation with System.Transactions, and you don't have to worry about opening or closing database connections anymore.  With Ado.Net transactions, you do still have to fiddle with transaction enlistment, so you still have to pass in transaction objects (good reason to not use it, System.Transactions is easier to use).&lt;br /&gt;&lt;br /&gt;For most common web apps, using connection-per-request and System.Transactions improves code quality and reduces the amount of code you have to write.  That's good for everybody.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/05/connection-per-request-with-adonet.html';reddit_title='Connection per request with Ado.Net';digg_url='http://vampirebasic.blogspot.com/2009/05/connection-per-request-with-adonet.html';digg_title='Connection per request with Ado.Net';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-857871922936792586?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/857871922936792586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/05/connection-per-request-with-adonet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/857871922936792586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/857871922936792586'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/05/connection-per-request-with-adonet.html' title='Connection per request with Ado.Net'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-4160409457765476881</id><published>2009-05-11T12:43:00.010-05:00</published><updated>2009-05-11T14:06:56.382-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><title type='text'>Those wacky Java guys, and their Eclipse</title><content type='html'>How much did your company spend on Visual Studio.Net, just so you could write Asp.Net web applications?  How much more did they spend if they decided to get the fancy "Team Systems" edition (which they'll pay an annual subscription renewal for next year)?&lt;br /&gt;&lt;br /&gt;Then, you have to buy Resharper, because writing code without it is 35%* harder.  I would say that without Resharper, code is 50%* harder, except that you have to keep turning it off when you go to edit markup because of performance issues (boo, JetBrains, boo.  I know you can do better, I've seen TeamCity). &lt;br /&gt;&lt;br /&gt;Now, why mention all of this?  Because Eclipse does everything Resharper + Visual Studio.Net does, plus it makes Java not be (complete) poo. And its free.  And it makes a great desert topping.&lt;br /&gt;&lt;br /&gt;I've also been impressed with &lt;a href="http://www.springsource.org/"&gt;Spring&lt;/a&gt;, &lt;a href="https://www.hibernate.org/"&gt;Hibernate&lt;/a&gt;, and &lt;a href="http://struts.apache.org/2.1.6/index.html"&gt;Struts 2&lt;/a&gt;.  Struts integrates Spring, allowing Struts to just use Spring to obtain objects, all behind the scenes without writing any code.  Struts also integrates Dojo, a Javascript framework similar in function to JQuery.  The Struts-Dojo integration reminds me of what Asp.Net Ajax was trying to do with UpdatePanels, only it actually works. Yeah, I said it.&lt;br /&gt;&lt;br /&gt;To top it off, Spring is (unsurprisingly) easier to use in the Java world, as you don't have to specify assembly location or version to the Spring runtime...what with Java not having assemblies and all.&lt;br /&gt;&lt;br /&gt;Hibernate now uses annotation (attributes in C#) based mapping, doing away with xml mapping files, and Eclipse allows you to generate your entities right off the database.  Furthermore, Struts (God bless them), is not strictly typed, so there is no type casting done in the jsp markup, and no writing weird little helper functions to get around C# and Asp.Net's seeming lack of cohesion.&lt;br /&gt;&lt;br /&gt;You know, stuff like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:label runat="server" ID="SomesuchImportantLabel" value='&amp;lt;%# Convert.ToString(((DataEntity) container.DataItem).DomainDataItem.SomeDate) %&amp;gt;'/gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Would look like this in Struts:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;s:property value="DataEntity.SomeDate" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Hey, Asp.Net and C# teams.  You guys ever talk to each other about that whole Web Forms situation?  It kinda sucks.  Sorry to be rude about it, but VB.Net works seamlessly in Web Forms and with C# you have to do all that clunky casting.  It'd be nice to leverage that slick "dynamic" behavior in the new C# language in Web Forms by default.  It would put an end to all of that carpel-inducing cast-ification.  Granted, your MVC stuff is MUCH better, and more comparable to Struts 2...I digress.&lt;br /&gt;&lt;br /&gt;What's not to love?  Err...well I did run into a few problems.&lt;br /&gt;&lt;br /&gt;Eclipse's jsp editor has an irritating bug in it where it eventually just quits providing code completion, and pops up a dialog every time you press a key, telling all about this marvelous StackOverflowException that it discovered.  Closing and reopening the jsp file fixes the problem, but it is disruptive, none-the-less.&lt;br /&gt;&lt;br /&gt;Since Struts 2 isn't strictly typed, when you type in something incorrectly, it will just politely ignore it. This bit me mostly because I didn't expect it, given Asp.Net's ruler-to-the-hand response to typing things incorrectly.&lt;br /&gt;&lt;br /&gt;Another thing that struck me was how easy it was to configure a JSP application.  The web.xml file is tiny, and once you set it up, you can ignore it forever more. This as contrasted to how unbelievably annoying it was to try to find all of the dependencies for the technologies I was using.  ClassNotFoundExceptions sent me to the internet more than once trying to scrounge up which jar file a particular class was hidden.&lt;br /&gt;&lt;br /&gt;The last thing that slowed me down was not JavaEE, Tomcat, Eclipse, Struts, or JSP.  It was the database server.  Since I like making things harder than the should be, I decided to use a database server with which I have limited familiarity, PostgeSQL 8.3.  Very good database.  Except, the damned thing doesn't care for upper-cased letters (as I've noted before in another post).  Placing escaped double-quotes into the JPA mapping annotations and explicitly defining catalog, schema, and name is a must if you use upper case characters and PostgreSQL, an issue I would never have encountered with MS SQL Server (it only gets pissy about spaces in object names).  &lt;br /&gt;&lt;br /&gt;The JPA development aspect in Eclipse isn't really astute enough to recognize the double-quote trick with PostgreSQL, and it gets upset when you put them in ('I don't know what this "Monkey" table is, you should have a Monkey table instead, I saw it on the DB.').&lt;br /&gt;&lt;br /&gt;Despite the learning curve involved in switching from the .Net realm to Java, and indeed, most of my issues fall into the learning curve category, I wouldn't hesitate to suggest a survey mission into that world to any company trying to write a brand-new application or perform a serious (Web Forms to ASP.Net MVC) upgrade.  Especially since Asp.Net MVC and Struts 2 are very competitive, feature-wise.&lt;br /&gt;&lt;br /&gt;*Figures not to scale.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/05/those-wacky-java-guys-and-their-eclipse.html';reddit_title='Those wacky Java guys, and their Eclipse';digg_url='http://vampirebasic.blogspot.com/2009/05/those-wacky-java-guys-and-their-eclipse.html';digg_title='Those wacky Java guys, and their Eclipse';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-4160409457765476881?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/4160409457765476881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/05/those-wacky-java-guys-and-their-eclipse.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4160409457765476881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4160409457765476881'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/05/those-wacky-java-guys-and-their-eclipse.html' title='Those wacky Java guys, and their Eclipse'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-282487425534208111.post-7985401641335591618</id><published>2009-04-11T10:22:00.004-05:00</published><updated>2009-04-11T11:15:52.781-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>ASP.Net Ajax in Mono</title><content type='html'>In a recent discussion with a friend of mine, it was brought to my attention that one of the additions in Asp.Net Ajax (the features located in System.Web.Extensions.dll) was the ability for asmx web services to emit lean-and-sexy JSON instead of tubby-and-pimply SOAP.&lt;br /&gt;&lt;br /&gt;This is an exceptionally cool feature, since it effectively gets you out of having to deal with the horrifically complicated configuration involved in setting up WCF, just to get JSON to your client script.&lt;br /&gt;&lt;br /&gt;Since web applications are becoming more client-script/web service oriented these days, I was curious at how well these kinds of ASP.Net applications would port to &lt;a href="http://www.mono-project.com"&gt;Mono&lt;/a&gt;.  After all, with the economy being what it is, some companies are becoming interested in ways to continue to innovate while saving some money, and Mono runs ASP.Net on Linux.&lt;br /&gt;&lt;br /&gt;In order to get started quickly, I got a copy of VMWare Player (which is free), and downloaded the VMWare image from the Mono project's web site for Mono 2.4.  When I started the image, I discovered that everything I needed to start experimenting was ready to go out of the box.  There were some samples, and a copy of the new version of MonoDevelop, just waiting for me.&lt;br /&gt;&lt;br /&gt;The first thing I did was to create a new ASP.Net web project in C#, and create an asmx web service that would return a complex type of some sort, and then use JQuery on the Default.aspx to call the web service.  I used the &lt;a href="http://www.json.org"&gt;JSON2.js&lt;/a&gt; serializer on the client side to verify that the output by just deserializing it.&lt;br /&gt;&lt;br /&gt;The initial results were a disaster.  All I could get from Mono's asmx web service was XML output, despite putting the ScriptMethodAttribute on my web service method.  ScriptMethodAttribute tells the asmx HttpHandler to output in JSON format.&lt;br /&gt;&lt;br /&gt;Assuming (incorrectly, as I later discovered) that I had found a rather silly bug in the Mono class library, I tested the exact same code in Microsoft's ASP.Net...which proceeded to work as expected.&lt;br /&gt;&lt;br /&gt;After a bit of a break, I started thinking about how, exactly, MS got the old asmx HttpHandler to output JSON without modifying the existing class library.  After all, when the smart folks as MS started adding in the 3.0 and 3.5 class libraries, they vowed to not change the existing class library if it wasn't truly necessary.&lt;br /&gt;&lt;br /&gt;I took another look at my web.config file in Visual Studio and discovered what magic made this possible:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;httpHandlers&amp;gt;&lt;br /&gt;    &amp;lt;remove verb="*" path="*.asmx"/&amp;gt;&lt;br /&gt;    &amp;lt;add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;/httpHandlers&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In Visual Studio, the default web.config unwires the old asmx http handler, then wires up a new asmx http handler that lives in System.Web.Extensions.dll.  The old handler is still unaware of JSON, the new handler takes care of all of this instead.&lt;br /&gt;&lt;br /&gt;The default web.config MonoDevelop created did not contain these modifications the the httpHandler section.  Fortunately, everything about the &amp;lt;add&amp;gt; line was the same except for the assembly version (Really? You got the public key token the same but not the assembly version? Why?).  Once I modified web.config, I got JSON output from the asmx.&lt;br /&gt;&lt;br /&gt;I know not everything in ASP.Net 2.0 is working in Mono, but its really satisfying to see that the team working on it have implemented the parts that are most interesting to everyday web developers.  I'm looking forward to seeing what cool bits the next release of Mono will bring.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/04/aspnet-ajax-in-mono.html';reddit_title='ASP.Net Ajax in Mono';digg_url='http://vampirebasic.blogspot.com/2009/04/aspnet-ajax-in-mono.html';digg_title='ASP.Net Ajax in Mono';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-7985401641335591618?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/7985401641335591618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/04/aspnet-ajax-in-mono.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/7985401641335591618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/7985401641335591618'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/04/aspnet-ajax-in-mono.html' title='ASP.Net Ajax in Mono'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-282487425534208111.post-5526574278784395145</id><published>2009-03-16T10:47:00.006-05:00</published><updated>2009-03-20T22:39:21.943-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>ASP.Net MVC Partial Rendering Vs. JSON</title><content type='html'>I've been doing a little research on ASP.Net MVC, now that it's in RC instead of "Hey, don't trust what we're releasing because we're still changing a lot of stuff"-Preview Release.  I was initially a little miffed with the official ASP.Net MVC site, because in iteration #7 of their &lt;a href="http://www.asp.net/learn/mvc/#MVC_SampleApp"&gt;tutorial&lt;/a&gt;, they "Add Ajax functionality" by converting part of their page to an (MVC) ascx control, then partial rendering it when a script request hits it.  That's so...ghetto.  After all, JSON is the new hotness, right? And what was it that UpdatePanels did that everybody hated?  Partial rendering.&lt;br /&gt;&lt;br /&gt;That's when a chill went down my spine, as I (as it turns out erroneously) deduced that MS had decided on a One True (ghetto) Way, and the Rails folks would get to continue to mock their .Net brethren for having to jump through huge flaming hoops to just spit out that lean and sexy JSON.&lt;br /&gt;&lt;br /&gt;Fortunately for me, I was wrong about everything.  Partial rendering in MVC is not ghetto at all.  Its actually MVC architecturally correct, light-weight, and templatey-sweet. Also, you can easily return JSON from your MVC controller without so much as striking a match, never mind setting up the gasoline-soaked hoops.&lt;br /&gt;&lt;br /&gt;I'm not really interested in retyping the examples in the Asp.Net site, but if you go &lt;a href="http://www.asp.net/learn/mvc/tutorial-32-cs.aspx"&gt;here&lt;/a&gt; and scroll down to "Listing 3".  You'll see the tutorial author recycling a controller action to be Ajaxy and not Ajaxy at the same time.  Going back up the page a little, you can see what makes their stuff architecturally correct, the &lt;i&gt;Ajax.ActionLink&lt;/i&gt; helper, where you specify a route name and don't hard-code your Ajax request URL into script somewhere.&lt;br /&gt;&lt;br /&gt;For the vast majority of situations, the tutorial's example will suffice.  It keeps you from having to parse JSON on the client, it keeps you from having to loop objects on the client, and as long as you don't get crazy with it and limit the amount of HTML you send back (data paging = good), it should be quite alright on the bandwidth consumption.&lt;br /&gt;&lt;br /&gt;As for the JSON, if you need or want it (it is lean and sexy, after all), all you have to do is this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Public Class SampleController&lt;br /&gt;    Inherits System.Web.Mvc.Controller&lt;br /&gt;&lt;br /&gt;    Function Get(ByVal Id As Integer) As ActionResult&lt;br /&gt;        Return Me.Json(SampleDataRepository.Get(Id))&lt;br /&gt;    End Function&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it.  No having to muck about with WCF or its Configuration Files of Unlimited Confusion +5, no inexplicable PleaseReturnJsonIfYouDontMindSoMuchThanksAttribute().  If you wanted to be strong-typed about it, you could change the function's return type to JsonResult, but if you were going to use the same method to spit out the View and JSON, because you like the word "Get", that may not be very helpful.&lt;br /&gt;&lt;br /&gt;I really wish they had covered the JSON alternative in their tutorial.  They might have mentioned that hard-coding "/Sample/Get" into your JQuery is naughty in MVC, because it defeats the purpose of routing. They could have also mentioned that you could write in the url from the server side view using &lt;i&gt;Url.Action()&lt;/i&gt; from server side code, but they didn't.&lt;br /&gt;&lt;br /&gt;Sometimes it makes me happy to be wrong.  I like finding out that things will be easier because the MVC team at MS is listening, cares, and did a good job.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/03/aspnet-mvc-partial-rendering-vs-json.html';reddit_title='ASP.Net MVC Partial Rendering Vs. JSON';digg_url='http://vampirebasic.blogspot.com/2009/03/aspnet-mvc-partial-rendering-vs-json.html';digg_title='ASP.Net MVC Partial Rendering Vs. JSON';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-5526574278784395145?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/5526574278784395145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/03/aspnet-mvc-partial-rendering-vs-json.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/5526574278784395145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/5526574278784395145'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/03/aspnet-mvc-partial-rendering-vs-json.html' title='ASP.Net MVC Partial Rendering Vs. JSON'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-5137220663619326362</id><published>2009-02-27T10:04:00.006-06:00</published><updated>2009-03-10T08:49:52.833-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Architecture'/><title type='text'>Windows Integrated Security in ASP.Net</title><content type='html'>I recently saw a &lt;a href="http://news.slashdot.org/article.pl?sid=09/03/02/1518234"&gt;story&lt;/a&gt; about how the new president of the US was interested in investing millions of dollars in "cybersecurity," whatever all that entails (and being your typical Slashdot reader, I didn't read the actual story).  Maybe Mr. Obama's worried about &lt;a href="http://en.wikipedia.org/wiki/Borg_(Star_Trek)"&gt;the Borg&lt;/a&gt; selling national secrets to the Ayatollah.&lt;br /&gt;&lt;br /&gt;We, the app developers, can improve the security of our public facing web apps by spending far less than...wait for it...one &lt;i&gt;million&lt;/i&gt; dollars, and the solution is Windows Integrated Security.&lt;br /&gt;&lt;br /&gt;Many people think of Windows Integrated Security as the SSO (Single Sign On) solution to save users the trouble of keeping Post-It sticky notes on the underside of their keyboards, and unbelievably inappropriate for web applications that need to be exposed to the public, but Windows Integrated Security is also good for securing Service Processes. You know, like IIS and Sql Server.&lt;br /&gt;&lt;br /&gt;If you've never read up about security and performance scaling with web apps, you'll quickly discover in your initial research that using Windows security to authenticate the client, and then impersonating that client to authenticate to the Sql Server is very auditable and secure, but performs poorly under load.  I think this is where most people give up and slap a password into their connection string.&lt;br /&gt;&lt;br /&gt;Microsoft has a rather dry article on securing distributed applications using the &lt;a href="http://msdn.microsoft.com/en-us/library/aa905320.aspx"&gt;Trusted Subsystem&lt;/a&gt; model, but for the typical single-server, single db web app, it boils down to this: use Forms Authentication to validate your user, set &amp;gt;identity impersonate="false"&amp;lt;, and assign your Asp.Net service account to some domain user account that pretty much can't do anything useful on the web or database server. This is easier done than said in newer versions of IIS, since all you have to do is set the user account of the relevant IIS app pool.  In 32 bit XP (yeah, 64 bit XP comes with a different version of IIS from 32 bit) and Server 2000, its a bit more convoluted, since the version of IIS that comes with them is Old-N-Busted(TM).  You will end up editing that spooky machine.config file to make SERVER\ASPNET stop being Asp.Net's man of the hour.&lt;br /&gt;&lt;br /&gt;Oh, and don't forget to run aspnet_regiis -ga [domain account] on your web server, or you'll get mad at it.  I really don't know what all, specifically, that command does, except that it "Grants Access" for everything a budding young domain account would need to actually run Asp.Net in IIS.&lt;br /&gt;&lt;br /&gt;Once you have your IIS process running ASP.Net under a domain account, its trivial to grant that account whatever access is needed in your Sql Server.  And guess what?  No passwords in the connection string for some nosy junior coder to be copying down to break your production database.  Million dollar cybersecurity, all for free.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/02/windows-integrated-security-in-aspnet.html';reddit_title='Windows Integrated Security in ASP.Net';digg_url='http://vampirebasic.blogspot.com/2009/02/windows-integrated-security-in-aspnet.html';digg_title='Windows Integrated Security in ASP.Net';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-5137220663619326362?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/5137220663619326362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/02/windows-integrated-security-in-aspnet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/5137220663619326362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/5137220663619326362'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/02/windows-integrated-security-in-aspnet.html' title='Windows Integrated Security in ASP.Net'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-3764207887032424399</id><published>2009-02-24T10:31:00.004-06:00</published><updated>2009-02-24T11:27:00.594-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unit Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>EntLib gets serious about IoC</title><content type='html'>When I first saw MS's Enterprise Library, I was impressed.  EntLib is a high feature enterprise application development framework.  It makes ADO.Net suck less.  It makes logging suck less. It makes handling exceptions suck less.  Now it makes unit testing suck less with &lt;a href="http://msdn.microsoft.com/en-us/library/dd203225.aspx"&gt;Unity&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The Unity Application Block basically does the same thing that Castle Windsor and Spring.Net do, but it appears to be a little more flexible than Spring.Net.  One nice thing I noticed is that Unity can create classes even if they aren't specifically configured (unlike Spring.Net), cutting down on some of that janky XML configuration that EntLib seems to have trailing behind it wherever it goes.&lt;br /&gt;&lt;br /&gt;In addition to providing a basic IoC container, it provides what the EntLib developers (thankfully) call "Interception" or everyone else (cryptically) calls AOP, or Aspect Oriented Programming.  Interception basically gives you the ability to write common code once, point the common code at a set of classes and say things like "When methods on these classes blow up, you run, thereby logging the error."&lt;br /&gt;&lt;br /&gt;Of course, as I have mentioned &lt;a href="http://vampirebasic.blogspot.com/2009/01/ioc-you-in-morning-part-1.html"&gt;before&lt;/a&gt;, using an IoC container is to your benefit, as it encourages you to write code that can be wired up in unit tests or automated integration tests.&lt;br /&gt;&lt;br /&gt;After all, the MS EntLib developers &lt;a href="http://msdn.microsoft.com/en-us/library/cc440954.aspx#intro_whentouse"&gt;recognized the fundamental necessity&lt;/a&gt; for these IoC thing-a-ma-jigs:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;In general, you should use the Unity Application Block in the following situations:&lt;br /&gt;    * Your objects and classes may have dependencies on other objects or classes.&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ummm...who's code DOESN'T have classes that depend on other classes?  The COBOL guys?&lt;br /&gt;&lt;br /&gt;I haven't experimented with Unity yet to see how well it works with ASP.Net, but apparently David Hayden &lt;a href="http://davidhayden.com/blog/dave/archive/2008/02/14/ASPNETMVCFrameworkUnityDependencyInjectionContainerPartII.aspx"&gt;has&lt;/a&gt;, at least with MVC.  WebForms will definitely have to be different, you'll probably have to write a special System.Web.UI.Page derived base class to easily gain access to your Unity container (the Spring guys had to for their ASP.Net support).  You'll also want to make sure your Unity container lives in application scope, as Mr. Hayden did so creatively.&lt;br /&gt;&lt;br /&gt;If you're in a shop that takes advantage of the services of Enterprise Library, you'd be missing a prime opportunity to improve quality and productivity if you're not at least checking out Unity.  I mean, its already in the box, you may as well look at it.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/02/entlib-gets-serious-about-ioc.html';reddit_title='EntLib gets serious about IoC';digg_url='http://vampirebasic.blogspot.com/2009/02/entlib-gets-serious-about-ioc.html';digg_title='EntLib gets serious about IoC';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-3764207887032424399?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/3764207887032424399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/02/entlib-gets-serious-about-ioc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3764207887032424399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3764207887032424399'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/02/entlib-gets-serious-about-ioc.html' title='EntLib gets serious about IoC'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-8184764652439435394</id><published>2009-02-10T22:28:00.010-06:00</published><updated>2009-02-24T11:36:54.505-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><title type='text'>NHibernate with PostgreSQL</title><content type='html'>PostgreSQL is an open source database server that is sadly ignored in the .Net world.  For one thing, its free.  For another, it isn't as heavy an install as SQL Server 2005, Developer Edition ($50), which is important to someone like me, who has a laptop with sadly lacking fixed-disk storage capacity.  That's back story number one.&lt;br /&gt;&lt;br /&gt;NHibernate attracted my attention when the failures of MS Entity Framework left me feeling &lt;a href="http://vampirebasic.blogspot.com/2009/01/nature-of-entity-framework-is-suffering.html"&gt;cheated&lt;/a&gt; and the little grievances with Linq To Sql left me wanting for more.  Neither are what I would call "nice" when used with a web app, they get pissy about reconnecting an entity fetched on one HTTP request and saved on another, which, interestingly enough, is &lt;i&gt;exactly&lt;/i&gt; what &lt;i&gt;every&lt;/i&gt; web app known to man does. That's back story number two.&lt;br /&gt;&lt;br /&gt;This situation of having two toys I wanted to play with led me to the desire to hook my toys together in a small, contrived solution, just to see if I could figure out how to get them to work.&lt;br /&gt;&lt;br /&gt;In my playing, I have discovered a couple of things about both technologies:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;PostgreSQL is &lt;i&gt;not&lt;/i&gt; SQL Server. They are monstrously different, but the differences can trip you up.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;NHibernate is not hard...unless you fail to install the xml schemas into Visual Studio.  Without Intellisense enabled on the mapping files, writing the .hbm.xml files quickly goes from trivial to trying.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Open source software deserves its reputation for lacking documentation. That being said, what &lt;i&gt;is&lt;/i&gt; there is extremely valuable, and what &lt;i&gt;isn't&lt;/i&gt; there is probably in some forum somewhere, if you search for it long enough.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;One thing that kept tripping me up over and over again was the way PostgreSQL handles object (schema, table, column, view, etc.) names. For whatever reason, it assumes that all object names are in lower case, even when you type them in mixed or upper case on a query.  For example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT * FROM Books&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;gets converted to &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT * FROM books&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I can't even begin to understand why it does this, but it does. Seems like extra work to me, but it is what it is. If you place double quotes around the object names&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT * FROM "Books"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;then it retains the object names just the way you type them.&lt;br /&gt;&lt;br /&gt;Now, that's really not that terrible.  You have to place square brackets around object names that SQL Server finds nappy, but I was somewhat offended by NHibernate's PostgreSQL 8.2 "dialect," the plug-in giblets that translate NHibernate's platform-independant queries into the server's native SQL, in that it didn't automatically place double-quotes around everything, whether I needed it or not.  Apparently this is a long-standing complaint with this bit of code, I actually found a bug against it that was several years old on the Java version of Hibernate for just this very problem, and yet, there it lies, unfixed. Fortunately, there is another way.&lt;br /&gt;&lt;br /&gt;The obvious solution is to add the optional table and column attributes to the mapping files and place backticks (`) around the values.  Because .Net developers use backticks &lt;i&gt;every day&lt;/i&gt; and that's blatantly obvious to anybody that that is the solution.  It has to be obvious to everybody else, because I couldn't find it in the NHiberate documentation anywhere. &amp;lt;/sarcasm&amp;gt;&lt;br /&gt;&lt;br /&gt;One of the big theoretical advantages to NHibernate is that it abstracts you away from the db vendor by way of its mapping files and query methods (HQL and Criteria Queries).  I'm not sure I completely buy into that theory.  With what I've experienced, the mapping files would need modifying when moving from SQL Server to PostgreSQL, although none of your VB/C# code would need any attention. Even so, cleaning up all those mapping files would be non-trivial in a large enough existing application.&lt;br /&gt;&lt;br /&gt;In conclusion, despite NHibernate's leaky abstractions on PostgreSQL, I could see how a SQL Server developer could come to love using it.  It could be a specific boon to those using Asp.Net MVC as well as those who use Web Forms.  I look forward to trying it in scenarios where Linq to Sql comes up short and Entity Framework fails miserably.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/02/nhibernate-with-postgresql.html';reddit_title='NHibernate with PostgreSQL';digg_url='http://vampirebasic.blogspot.com/2009/02/nhibernate-with-postgresql.html';digg_title='NHibernate with Postgresql';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-8184764652439435394?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/8184764652439435394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/02/nhibernate-with-postgresql.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/8184764652439435394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/8184764652439435394'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/02/nhibernate-with-postgresql.html' title='NHibernate with PostgreSQL'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-282487425534208111.post-186879867267517828</id><published>2009-01-28T11:24:00.006-06:00</published><updated>2009-01-28T12:03:26.009-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>SQL Server, NULL varchar vs empty varchar</title><content type='html'>It always amazes me that people LOVE NULLable fields in database tables.  I find very little value in them, as you can represent "empty" as a nullstring (zero-length string) instead, and NULLs tend to make querying the database just a little bit harder to deal with, and what we developers don't really need is for our lives to be any harder.&lt;br /&gt;&lt;br /&gt;The only thing that I can figure is that people believe that a NULL varchar in SQL Server takes up less space than an empty NOT NULL varchar.  I devised a test to see if this was true.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;create table temp(data varchar(500) NULL)&lt;br /&gt;create table temp2(data varchar(500) NOT NULL)&lt;br /&gt;&lt;br /&gt;declare @counter int&lt;br /&gt;set @counter = 0&lt;br /&gt;while (@counter &lt; 50000)&lt;br /&gt;BEGIN&lt;br /&gt; insert into temp(data)&lt;br /&gt; values(NULL)&lt;br /&gt;&lt;br /&gt; insert into temp2(data)&lt;br /&gt; values('')&lt;br /&gt;&lt;br /&gt; SET @Counter = @Counter + 1&lt;br /&gt;END&lt;br /&gt; &lt;br /&gt;exec sp_spaceused 'temp'&lt;br /&gt;exec sp_spaceused 'temp2'&lt;br /&gt;&lt;br /&gt;drop table temp&lt;br /&gt;drop table temp2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This script, when run on SQL Server 2005, shows that both tables are exactly the same size, proving that NULLS and empty strings take up the exact same space on the disk.&lt;br /&gt;&lt;br /&gt;The moral of the story is this: don't use NULLs if you think its saving you space, its a false economy.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/01/sql-server-null-varchar-vs-empty.html';reddit_title='SQL Server, NULL varchar vs empty varchar';digg_url='http://vampirebasic.blogspot.com/2009/01/sql-server-null-varchar-vs-empty.html';digg_title='SQL Server, NULL varchar vs empty varchar';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-186879867267517828?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/186879867267517828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/sql-server-null-varchar-vs-empty.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/186879867267517828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/186879867267517828'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/sql-server-null-varchar-vs-empty.html' title='SQL Server, NULL varchar vs empty varchar'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-282487425534208111.post-4386150367694995854</id><published>2009-01-21T19:46:00.005-06:00</published><updated>2009-01-21T20:37:01.142-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Mono'/><title type='text'>Mono 2.2 drops C# Script on the unsuspecting world</title><content type='html'>I discovered an interesting tidbit while perusing the Mono project's version 2.2 &lt;a href="http://www.mono-project.com/Release_Notes_Mono_2.2"&gt;Release notes&lt;/a&gt;.  Apparently, someone on the project hates the inflexibility of C# as much as I do.&lt;br /&gt;&lt;br /&gt;Scroll about half way down to the "C# Language" section, and you will discover something... "Compiler Services." Basically, the Mono team has come up with the C# version of the Javascript Eval() function, and an interactive shell, a-la Python or Perl.&lt;br /&gt;&lt;br /&gt;This was done to allow applications to provide C# as a macro language.  But it could be used to do all manner of interesting things, maybe to make small segments of code that can be modified at runtime, such as business rules processing.&lt;br /&gt;&lt;br /&gt;The real question of the day is, can you use it in your MS CLR based projects in addition to using it with Mono based projects?&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/01/mono-22-drops.html';reddit_title='Mono 2.2 drops C# Script on the unsuspecting world';digg_url='http://vampirebasic.blogspot.com/2009/01/mono-22-drops.html';digg_title='Mono 2.2 drops C# Script on the unsuspecting world';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-4386150367694995854?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/4386150367694995854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/mono-22-drops.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4386150367694995854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4386150367694995854'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/mono-22-drops.html' title='Mono 2.2 drops C# Script on the unsuspecting world'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-6762558997802443201</id><published>2009-01-20T20:34:00.010-06:00</published><updated>2009-03-10T08:16:53.669-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><title type='text'>The nature of Entity Framework is suffering</title><content type='html'>In my line of work, the vast majority of my development is web applications to support business operations.  Nothing fancy, and rarely anything exciting, but it requires some reasonable code quality and some ability to diagnose and support the running system.&lt;br /&gt;&lt;br /&gt;Since these web applications are not usually anything special, they should be relatively easy to create...and yet, writing a DAL for an "enterprisey" web app is tedious as can be imagined.  If you follow the conventional wisdom, you have to write sprocs, then write ADO.Net code to run the sprocs, then translate the data output into objects and return them.  Then to save, you have to translate objects into sproc calls again.&lt;br /&gt;&lt;br /&gt;Just typing the description of all of that makes me tired, so I'm always on the lookout for a way to get the "boss-man" to let me cut out the boiler-plate, carpel-tunnel inducing code typing and get to the job of actually creating quality applications.&lt;br /&gt;&lt;br /&gt;My current recommendation, after doing some research, is this:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Please, for the love of everything that is holy, &lt;b&gt;forget stored procedures ever existed&lt;/b&gt;. The only thing they add to your application is development cost.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Linq to SQL is a neat curio, but its really harder to use than regular SQL, despite its epic hipness. Use regular SQL instead and save yourself the trouble.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you're going to use regular SQL, save yourself the annoyance of having to hand-code object mapping in your C#, and generate that junk instead. MyGeneration is free, CodeSmith is cheap, you have no excuse for wasting your employer's money. Just don't use .Net Tiers (of agony).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ADO.Net Entity Framework is probably the worst data access technology I've ever used, sitting at the right hand of Satan. &lt;b&gt;Don't ever use this in a web app&lt;/b&gt;. It will only make you angry.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;I expect that after I use NHibernate in a production development environment, I will simply replace all of the above recommendation with "just use NHibernate, forget about everything else," but I would have said the same thing about Entity Framework until it punished me for trying to use it.&lt;br /&gt;&lt;br /&gt;When I first started playing with EF, I thought it was going to be cool.  Then it boxed my ears. In order to use an entity fetched in one web request in another web request, you have to manually detach it from the database context...which isn't Ok. I don't have to do this in Linq to Sql.&lt;br /&gt;&lt;br /&gt;Attaching items for update is almost completely impossible with a many-to-many relationship.  I never could find the magic incantation to get it to just save an object graph without re-selecting it off the database, then manually updating the object's properties, which sounds suspiciously similar to the whole mapping thing that I don't want to manually do.&lt;br /&gt;&lt;br /&gt;Actually, Entity Framework makes &lt;a href="http://efvote.wufoo.com/forms/ado-net-entity-framework-vote-of-no-confidence/"&gt;many other&lt;/a&gt; people angry, but not apparently for the reason it makes me angry.&lt;br /&gt;&lt;br /&gt;Entity Framework, its not just for WinForms...oh, wait, yes it is.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2009/01/nature-of-entity-framework-is-suffering.html';reddit_title='The nature of Entity Framework is suffering';digg_url='http://vampirebasic.blogspot.com/2009/01/nature-of-entity-framework-is-suffering.html';digg_title='The nature of Entity Framework is suffering';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-6762558997802443201?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/6762558997802443201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/nature-of-entity-framework-is-suffering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/6762558997802443201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/6762558997802443201'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/nature-of-entity-framework-is-suffering.html' title='The nature of Entity Framework is suffering'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-3223735059259816657</id><published>2009-01-08T09:04:00.004-06:00</published><updated>2009-01-20T21:15:10.813-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unit Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>IoC you in the morning, Part 2</title><content type='html'>In my previous (long winded) &lt;a href="http://vampirebasic.blogspot.com/2008/10/ioc-you-in-morning-part-1.html"&gt;post&lt;/a&gt; on IoC, I discussed in gory detail how write your own general object factory for obtaining testable objects in a running application.&lt;br /&gt;&lt;br /&gt;If you want to know more about why this is even necessary to begin with, read &lt;br /&gt;&lt;a href="http://martinfowler.com/articles/injection.html"&gt;this&lt;/a&gt; Martin Fowler article.  I can summarize it shortly for the impatient, however.  If your classes are hard-bound together in your application (they create instances of other classes that they need to work directly by using "New") then it makes them nearly impossible to test in NUnit without causing weird (writes bogus data to the db or file system) or performance sapping (reads or writes LOTS of bogus data to the db, then undoes its dirty deeds with a transaction rollback) side-effects (since you forgot to do the rollback) when running unit tests.&lt;br /&gt;&lt;br /&gt;Now, if you're like me, and you want to use somebody else's pre-written, pre-tested code to make your app run, the &lt;a href="http://springframework.net"&gt;Spring.Net&lt;/a&gt; IoC container of Java lineage is probably less annoying than writing your own factory on all but the smallest applications, and in the smallest applications, you probably won't even bother with a factory, you could just set everything up in Application scope or with Shared (static) members somewhere in the UI host code.&lt;br /&gt;&lt;br /&gt;Spring.Net's documentation is voluminous to the point of being overwhelming to the beginner, though it is well organized and fairly complete for the more popular sections of the framework.&lt;br /&gt;&lt;br /&gt;If you can cull out the portions of the documentation that you don't want, you will find out that Spring.Net's IoC container consists of a class that goes and finds objects and puts them together in a runnable form for you, and a configuration file/section that tells the class how to create those classes and glue them together at runtime.  The configuration file is highly flexible, you can place it directly inline in your app.config/web.config, you can place it in an easily accessible external file and access it by Asp.Net url (~/Config/SpringConfig.xml for example) or file path, or you can have it embedded in an assembly and have Spring.Net load its configuration directly from the dll.&lt;br /&gt;&lt;br /&gt;You furthermore have complete control over the instancing behavior of the objects.  You can specify any given object be created once and retained for eternity, returning the same object instance on every GetObject() call to Spring or created anew per GetObject() request.  With web apps, you can further specify that a class is created once per web request, once per web session, or once per web application, with the caveat that when using Session state, your Session state should be set to InProc, or you suffer object serialization (which SUCKS! for performance).  The default for the settings is for an object to exist eternally and live in the web Application state.  You can also have the container create objects eagerly, without waiting for you to ask for them, or "lazy-init" them, where it doesn't create them until it absolutely needs to do so.  The default is to create objects in advance.&lt;br /&gt;&lt;br /&gt;I usually have the container lazy-init objects and retain them for the lifetime of the web request only for my web apps.  Its just easier to write code against this instancing model, and it is relatively easy on the hardware's resources.  This isn't the MAXIMUM SCALABILITY solution, but when that becomes a requirement, you'll be refactoring code anyway.&lt;br /&gt;&lt;br /&gt;For people who develop in Asp.Net, there are additional goodies in Spring.Net to make life easier.  There is a base page provided by Spring.Net that derives from System.Web.UI.Page, unsurprisingly called Spring.Web.UI.Page that provides easy access to the container class.  There is some additional configuration that must be done to make Spring.Net set up its base page correctly, but with a little copy-and-paste from their documentation, setting up the Asp.Net extensions are a snap, and the Spring.Net base page includes its own ghetto-MVC data binding that you can use or not as you see fit.&lt;br /&gt;&lt;br /&gt;I know this post is pretty shy on code, but Mr. Fowler seems to have already done an excellent job of explaining the details of using Spring.  I hope Spring.Net makes your software suck less, as it has with mine.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2008/10/ioc-you-in-morning-part-2.html';reddit_title='IoC you in the morning, Part 2';digg_url='http://vampirebasic.blogspot.com/2008/10/ioc-you-in-morning-part-2.html';digg_title='IoC you in the morning, Part 2';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-3223735059259816657?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/3223735059259816657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/ioc-you-in-morning-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3223735059259816657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3223735059259816657'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2009/01/ioc-you-in-morning-part-2.html' title='IoC you in the morning, Part 2'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-9184201327643997263</id><published>2008-12-03T13:32:00.007-06:00</published><updated>2008-12-04T09:24:02.963-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='temporary tables'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>A legitimate use for temporary tables</title><content type='html'>Temp tables are those monstrosities that start with # in SQL Server.  They exist in a netherworld in between your database and the TempDB database, and they only exist for the current connection...unless you're crazy enough to use a ## temp table, then they're in a global TempDB netherworld...then they mysteriously break your code.&lt;br /&gt;&lt;br /&gt;In general, these things are rightfully maligned because they usually just cause way more trouble than they're worth, especially when an error occurs in the database that somehow ends up with the temp table not getting DROPped.  Conventional wisdom says to use table-valued variables instead...and yet, if you're trying to load half-a-million rows into a table variable, you're hosed.&lt;br /&gt;&lt;br /&gt;Here's the scenario where the evil little buggers actually work: bulk loading a flat file into a relational structure through TSQL because SSIS is (still and always will be) crap:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Create an XML Format File to describe your flat file to the DB server&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a temp table wiht columns that you like from your file&lt;/li&gt;&lt;br /&gt;&lt;li&gt;INSERT INTO #EvilTempMonster ... FROM OPENROWSET(BULK 'file name goes here' FORMATFILE='format file name goes here')&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Place indexes on your temp table&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Load the relational structures to your heart's content.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Drop the temp table&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Do your bulk load outside of a transaction (you aren't going to modify your file from inside SQL), but do all of your relational INSERT/UPDATE stuff in a transaction, wrapped in a TRY...CATCH block, and on catch, ROLLBACK.&lt;br /&gt;&lt;br /&gt;It should look something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;DECLARE @ErrorMessage nvarchar(MAX)&lt;br /&gt;&lt;br /&gt;--Just make sure your temp table can't somehow&lt;br /&gt;-- screw with you and ruin your day.&lt;br /&gt;IF object_id('tempdb..#MyFlatFile') IS NULL&lt;br /&gt;    DROP TABLE #MyFlatFile&lt;br /&gt;&lt;br /&gt;CREATE TABLE #MyFlatFile(...columns rock...)&lt;br /&gt;&lt;br /&gt;--Mmmm, much better than BULK INSERT.&lt;br /&gt;--Even if you have to make this dynamic SQL to&lt;br /&gt;-- vary the file name and format file name.&lt;br /&gt;INSERT INTO #MyFlatFile(...columns again...)&lt;br /&gt;SELECT ...flat file column list...&lt;br /&gt;FROM OPENROWSET(BULK 'filename.txt' FORMATFILE='formatfile.xml')&lt;br /&gt;&lt;br /&gt;CREATE CLUSTERED INDEX IX_ImportantMatchField&lt;br /&gt;ON #MyFlatFile (ImportantId)&lt;br /&gt;&lt;br /&gt;BEGIN TRY&lt;br /&gt;  BEGIN TRANSACTION&lt;br /&gt;&lt;br /&gt;  INSERT INTO TableA&lt;br /&gt;  FROM #MyFlatFile&lt;br /&gt;  WHERE #MyFlatFile.ImportantId NOT IN (SELECT DISTINCT MyImportantId FROM TableA)&lt;br /&gt;&lt;br /&gt;  ...Other inserts/updates...&lt;br /&gt;&lt;br /&gt;  COMMIT&lt;br /&gt;END TRY&lt;br /&gt;BEGIN CATCH&lt;br /&gt;  ROLLBACK&lt;br /&gt;  SET @ErrorMessage = ERROR_MESSAGE()&lt;br /&gt;END CATCH&lt;br /&gt;&lt;br /&gt;DROP TABLE #MyFlatFile&lt;br /&gt;&lt;br /&gt;IF @ErrorMessage IS NOT NULL&lt;br /&gt;  RAISERROR(@ErrorMessage, 16, 1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;At least, that's one way to do it.  You could just do the DDL and bulk load inside the transaction too, and that would be easier on the programmer, I'm just unsure of the performance implications.&lt;br /&gt;&lt;br /&gt;With my script, I can load half-a-million rows into 3 different related tables, reducing out duplication, scrubbing out double-quotes (thanks Excel), inserting new rows and updating existing rows in under 3 minutes on what is a pretty "slow" development server.&lt;br /&gt;&lt;br /&gt;Why go through all of this when SSIS has a pretty graphical designer?  My IS packages would not execute in the context of my web server, running under a least-privileged-user account (whoops!).  Furthermore, I could not use transactions within the IS packages because of permissions problems involving the Distributed Transaction Coordinator. WTF is it using that for? SSIS COM at the core. Awww, yeah! That's what I'm talkin' about!&lt;br /&gt;&lt;br /&gt;Has anybody else found a use for temp tables that made you move them from the "Evil-Never Use" category to the "Correct tool for some circumstances" category?&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2008/12/legitimate-use-for-temporary-tables.html';reddit_title='A Legitimate use for temporary tables';digg_url='http://vampirebasic.blogspot.com/2008/12/legitimate-use-for-temporary-tables.html';digg_title='A Legitimate use for temporary tables';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-9184201327643997263?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/9184201327643997263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2008/12/legitimate-use-for-temporary-tables.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/9184201327643997263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/9184201327643997263'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2008/12/legitimate-use-for-temporary-tables.html' title='A legitimate use for temporary tables'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-2295395440503566698</id><published>2008-11-12T09:34:00.006-06:00</published><updated>2009-01-20T21:15:37.131-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>How to make delimited strings in C#</title><content type='html'>In prior popular MS programming languages and within the COM runtime environment, strings were &lt;i&gt;mutable&lt;/i&gt; that is, the program could change the contents and size of a string in memory without having to copy the whole thing over in memory.&lt;br /&gt;&lt;br /&gt;In the world of .Net, though, strings are &lt;i&gt;immutable&lt;/i&gt;, which means once they are made, any changes to them causes them to be completely copied in memory to be modified.  As you can imagine, this is quite painful, performance-wise.  This is why the .Net runtime has a StringBuilder class, which mimics the effects of real mutable strings.&lt;br /&gt;&lt;br /&gt;Now, in mutable string languages, building a delimited string quickly was as simple as doing this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Dim delimiter = ""&lt;br /&gt;Dim delimitedString = ""&lt;br /&gt;&lt;br /&gt;For Each Item In intArray&lt;br /&gt;    delimitedString = delimitedString &amp; delimiter &amp; CStr(intArray)&lt;br /&gt;&lt;br /&gt;    'Single char assignments are super cheap&lt;br /&gt;    ' because the string has already been allocated.&lt;br /&gt;    delimiter = ","&lt;br /&gt;End For&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Do that in VB.Net or C#, and it'll run like poo, because every time the delimiter is assigned, a new string is allocated in memory and then its value set, versus what VB6 did, which was to just change char[0] of the delimiter string to a comma...over and over and over again.&lt;br /&gt;&lt;br /&gt;Here's how you do the same thing in a .Net language and retain performance:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if(intArray == null || intArray.Length == 0)&lt;br /&gt;    return string.Empty;&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;    StringBuilder sb = new StringBuilder(intArray[0]);&lt;br /&gt;&lt;br /&gt;    for(int itemCounter = 0; itemCounter &lt; intArray.Length; itemCounter++)&lt;br /&gt;    {&lt;br /&gt;        sb.AppendFormat(", {0}", intArray);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return sb.ToString();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In VB:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Return Join(intArray, ", ")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I couldn't tell you what kind of performance the VB Join() method gets (and I have no doubt writing a loop yourself is faster), but you can't argue with the ease of it.  And before you say C# can use string.Join(), you have to know that string.Join() requires its input array to already be an array of strings, which would have required me to loop through the int array above and make a string array just to call string.Join(). Which would be stupid.  Because you never loop over a data set twice when once will do the trick.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2008/11/how-to-make-delimited-strings-in-c.html';reddit_title='How to make delimited strings in C#';digg_url='http://vampirebasic.blogspot.com/2008/11/how-to-make-delimited-strings-in-c.html';digg_title='How to make delimited strings in C#';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-2295395440503566698?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/2295395440503566698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2008/11/how-to-make-delimited-strings-in-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/2295395440503566698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/2295395440503566698'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2008/11/how-to-make-delimited-strings-in-c.html' title='How to make delimited strings in C#'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-4746196678456418645</id><published>2008-11-03T18:31:00.005-06:00</published><updated>2008-11-03T19:53:49.316-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linq'/><title type='text'>Linq to Magic Smoke</title><content type='html'>The sky is falling!  The sky is falling!  Cats and dogs, living in sin!&lt;br /&gt;&lt;br /&gt;Microsoft let the Magic Smoke out of Linq to SQL.&lt;br /&gt;&lt;br /&gt;I don't really understand all the noise about it.  All they said is that its not going away, but its not going to get better, either, so if you wouldn't so much mind, please use ADO.Net EF instead.&lt;br /&gt;&lt;br /&gt;I saw some blog posters (the most vocal and afraid) who were bemoaning the apocryphal demise of doing that easy, easy data access that Linq to Sql has impressed me with.&lt;br /&gt;&lt;br /&gt;Now take a quick peek at what the MSDN article says of Linq to Entities in conjunction with ADO.Net EF&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx#ado.netenfrmovw_topic4"&gt;here&lt;/a&gt;.  Drink it in.&lt;br /&gt;&lt;br /&gt;If you didn't behold the coolness therein, I'll summarize.  You can do everything you could do in Linq to Sql, and it pretty much works in code the exact same way.  You probably won't even have to change that much of your code to switch it over.&lt;br /&gt;&lt;br /&gt;Here's what you get in addition:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Entity SQL&lt;/h4&gt; - Like HQL from NHibernate, this SQL-ish language gives you the flexibility to do just about anything you need with the database server, including server side paging and sorting.  Its vendor independent, as well, which should really rile the guys at Oracle.  T-SQL to query Oracle?  Preposterous!  If you hate it, don't use it.  Nobody will hate you if you don't.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Redefine entities that don't make any sense&lt;/h4&gt; - Some legacy data structures are insane.  Now you don't have to deal with that garbageoutside the DAL!  Write Business logic components...*NOW! with less suckage!* for your poor web developers to consume.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Join to that DataSet&lt;/h4&gt; - Many legacy DALs...ok, many current DALs...use ADO.Net DataSets.  Datasets are great, so a goodly number of DALs used them.  Now you can write new Business Logic, using both new and old data sources, because rewriting entire working DALs tends to cost heaping sums of cash, but you don't want to use the old-n-busted of the DataSet world.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;So everybody calm down about Linq to Sql.  MS doesn't want to waste money on developing two technologies that basically do the same thing, and they're not taking the keys to the Camero.  Of course, if they really wanted to save money, they would have written a hook to Linq for NHibernate.&lt;br /&gt;&lt;br /&gt;Stay tuned for MS "inventing" an IoC container instead of telling people that Spring.Net is for lusers.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2008/11/linq-to-magic-smoke.html';reddit_title='Linq to Magic Smoke';digg_url='http://vampirebasic.blogspot.com/2008/11/linq-to-magic-smoke.html';digg_title='Linq to Magic Smoke';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-4746196678456418645?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/4746196678456418645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2008/11/linq-to-magic-smoke.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4746196678456418645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4746196678456418645'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2008/11/linq-to-magic-smoke.html' title='Linq to Magic Smoke'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-4856147038905624794</id><published>2008-10-31T11:31:00.014-05:00</published><updated>2009-01-20T21:16:07.353-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unit Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>IoC you in the morning, Part 1</title><content type='html'>There's been quite a bit of harping lately on how everybody should, at the very least, be writing testable code, if not following the principles of Test Driven Design.  The fact of the matter is, you SHOULD be writing testable code, but nobody has ever make a concerted effort to put all the pieces together in a comprehensible without using make up words and phrases that make easy things hard to understand.&lt;br /&gt;&lt;br /&gt;The first thing you want to do when you are writing testable code, is to figure out which classes you are interested in testing.  Enterprisey code (if it isn't crap) is layered, like a cake.  On the bottom is your Data Access Layer (DAL), that keeps all that funky SQL crap out of the next layer up.  The next layer, then, is your Business Logic Layer.  It does the work.  The icing on the top is the UI Layer, which in the case of this posting will be ASP.Net.  Not that there's anything wrong with that.&lt;br /&gt;&lt;br /&gt;Inside the different respective layers, you can conceivably have more slices and layers if it helps achieve your ends...though most people don't.  Now, if your Enterprisey web app is laid out as above, then most of your actual work (mucking with files, interacting with external subsystems, manipulating data...the fun stuff) should be in your middle layer, your Business Logic Layer.  This is the layer you want to test.&lt;br /&gt;&lt;br /&gt;Now, sure, you can grab a copy of NUnit (my unit testing poison of choice) and go to town, but where do you start?  First of all, all of your BLL classes need to live in assembly(ies, whatever) separate from your UI.  Web projects/web sites are completely untestable from the NUnit perspective, because NUnit needs a dll to bind to.  Just make your BL a new project in your solution, set a project reference to it, and you'll never know the difference.&lt;br /&gt;&lt;br /&gt;The next step is to make your BL classes less aware of classes that they depend on.  This means that you have to stop creating DAL objects within your BL classes, and provide some mechanism to attach those DAL objects you need to the BL classes.&lt;br /&gt;&lt;br /&gt;There are a few ways to make that attachment.  One is to just make a constructor that takes all the DAL components.  That's for some things, but if you have a lot of DAL objects affixed to a single BL component, it gets pretty harry.&lt;br /&gt;&lt;br /&gt;VB:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Public Interface IDoPeople&lt;br /&gt; Function GetMyPeeps() As PersonEntity()&lt;br /&gt;End Interface&lt;br /&gt;&lt;br /&gt;Public Class PersonDataAccessObject&lt;br /&gt; Implements IDoPeople&lt;br /&gt;&lt;br /&gt; Public Function GetMyPeeps() As PersonEntity() Implements IDoPeople.GetMyPeeps&lt;br /&gt;   'Do Data Access Here&lt;br /&gt; End Function&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;Public Class PersonManager&lt;br /&gt; Private MyDAO As IDoPeople&lt;br /&gt;&lt;br /&gt; Public Sub New(ByVal DAO As IDoPeople)&lt;br /&gt;     MyDAO = DAO&lt;br /&gt; End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;C#:&lt;pre&gt;&lt;br /&gt;public interface IDoPeople&lt;br /&gt;{&lt;br /&gt; PersonEntity[] GetMyPeeps();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class PersonDataAccessObject : IDoPeeps&lt;br /&gt;{&lt;br /&gt; public PersonEntity[] GetMyPeeps()&lt;br /&gt; {&lt;br /&gt;    //Do data access stuff here.&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class PersonManager&lt;br /&gt;{&lt;br /&gt; IDoPeople MyDAO;&lt;br /&gt;&lt;br /&gt; public PersonManager(IDoPeople DAO)&lt;br /&gt; {&lt;br /&gt;    MyDAO = DAO;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, imagine that, with 8 different DAO arguments on the constructor. It works, but its ugly.  I much prefer to use properties for DAOs and other dependancies, like this:&lt;br /&gt;&lt;br /&gt;VB:&lt;pre&gt;Public Class PersonManager&lt;br /&gt; Private _MyDAO As IDoPeople&lt;br /&gt;&lt;br /&gt; Public Property MyDAO As IDoPeople&lt;br /&gt;     Get&lt;br /&gt;         Return _MyDAO&lt;br /&gt;     End Get&lt;br /&gt;     Set(Value As IDoPeople)&lt;br /&gt;         _MyDAO = Value&lt;br /&gt;     End Set&lt;br /&gt; End Property&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;C#:&lt;br /&gt;&lt;pre&gt;public class PersonManager&lt;br /&gt;{&lt;br /&gt; public IDoPeople MyDAO {get; set;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;That's just my preference.  I actually have a technical reason for preferring properties, but for the most part, it doesn't matter which way you do it.&lt;br /&gt;&lt;br /&gt;Also note the interface.  It is the key to making your Business Logic class testable.  The interface is basically a definition of what the BL class will accept as a Data Access Object.  It doesn't necessarily &lt;i&gt;have&lt;/i&gt; to be an instance of PersonManagerDataAccessObject, it could be anything that just kinda &lt;i&gt;looks&lt;/i&gt; like the PersonManagerDataAccessObject.  That means that the MyDAO property above is &lt;i&gt;mockable&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;The next issue to address isn't really how to test your code, but how to actually make the code work in the real system at runtime.  I mean, your BL component's properties have to get assigned, or the BL component won't work, right?&lt;br /&gt;&lt;br /&gt;I wrote a static class with a single static method on it to go through creating Business Logic components for me.&lt;br /&gt;VB:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Public Shared Class ObjectLocator&lt;br /&gt; Private Shared InjectableTypes As Dictionary(Of Type, Type)&lt;br /&gt;&lt;br /&gt; Public Shared Sub New()&lt;br /&gt;     InjectibleTypes = New Dictionary(Of Type, Type)()&lt;br /&gt;&lt;br /&gt;     InjectibleTypes.Add(GetType(VampireBasic.Data.IDoPeople, GetType(VampireBasic.Data.PersonDataAccessObject))&lt;br /&gt; End Sub&lt;br /&gt;&lt;br /&gt; Public Function GetManagedObject(ByVal objectName As String)&lt;br /&gt;     'Create components here, or fetch them from the cache.&lt;br /&gt; End Function&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;C#:&lt;br /&gt;&lt;pre&gt;public static class ObjectLocator&lt;br /&gt;{&lt;br /&gt; private static Dictionary&amp;lt;Type, Type&amp;gt; InjectibleTypes;&lt;br /&gt;&lt;br /&gt; public static ObjectLocator()&lt;br /&gt; {&lt;br /&gt;     InjectibleTypes = new Dictionary&amp;lt;Type, Type&amp;gt;();&lt;br /&gt;&lt;br /&gt;     InjectibleTypes.Add(typeof(VampireBasic.Data.IDoPeople), typeof(VampireBasic.Data.PersonDataAccessObject));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static object GetManagedObject(string objectName)&lt;br /&gt; {&lt;br /&gt;     //create components here, or fetch them from cache.&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The contents of GetManagedObject() are pretty complicated, but it basically does the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Go see if the object is in the per-http request cache (look at HttpRequest.Current.Items)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If its not in the cache, go see if its really something we can try to create...that means reflection.  Its ok to use reflection for this, because the resulting object will be cached for the rest of the request.  All reflection costs are paid only once&lt;br /&gt;per object lookup per http request.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Once its created, pull all of the properties off that are an interface of some sort--that's the technical reason why I used properties, because I know how reflection works for properties, and its pretty easy to deal with.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Go through the list of interfaces, and try to pull them from HttpContext.Items cache.  If its not there, check with the InjectableTypes dictionary. If the interface is in there, create an instance of the type it is associated with and cache it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now, this is the part where it gets a little specific to my task. I'm using LINQ, so there is a property on every InjectableTypes DAL object called "Database" that is derived from LINQ's DataContext class.  Since I know what that is, I just create ONE AND ONLY ONE DataContext and attach it to the DAL object.  Then cache the DataContext in HttpContext.Items.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;The whole point of the ObjectLocator in my project is to cache the DataContext object.  There are two reasons for this.  If you query LINQ for an entity more than once on the same DataContext object, LINQ will not query the database again for that entity, improving performance.  Second reason is transactions, which pretty much require you to keep your database connection open during the scope of the transaction.  If you do something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class TransactingBLComponent&lt;br /&gt;{&lt;br /&gt; public ILikeMonkeys MonkeyDAO;&lt;br /&gt;&lt;br /&gt; public void DoSomethingComplex&lt;br /&gt; {&lt;br /&gt;     Using(System.Transactions.TransactionScope txn = new TransactionScope())&lt;br /&gt;     {&lt;br /&gt;         MonkeyDAO.DoOneThing();&lt;br /&gt;         MonkeyDAO.DoAnotherThing();&lt;br /&gt;&lt;br /&gt;         txn.Complete();&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and you don't keep your database connection open for the duration of the TransactionScope, all manner of annoying things occur (MSDTC elevations, yuck).&lt;br /&gt;&lt;br /&gt;Since I don't create a new DataContext with every call to the MonkeyDAO, transactions work as they should.&lt;br /&gt;&lt;br /&gt;So, that's how I manage dependencies between objects in an Enterprisey web app.  Of course, you could just use Spring.Net, but where's the fun in that?&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2008/10/ioc-you-in-morning-part-1.html';reddit_title='IoC you in the morning, Part 1';digg_url='http://vampirebasic.blogspot.com/2008/10/ioc-you-in-morning-part-1.html';digg_title='IoC you in the morning, Part 1';digg_topic='programming';digg_skin='compact';digg_window='new'&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-4856147038905624794?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/4856147038905624794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2008/10/ioc-you-in-morning-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4856147038905624794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/4856147038905624794'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2008/10/ioc-you-in-morning-part-1.html' title='IoC you in the morning, Part 1'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-381665391120704134</id><published>2008-10-15T09:19:00.004-05:00</published><updated>2008-10-15T10:44:19.395-05:00</updated><title type='text'>Formal Properties</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Ahhh, yes. &lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Formal Properties&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; in a programming language are something that all mainstream .Net (and Delphi) developers have come to know and love.  It is quite easy to take something so simple for granted, especially if you are used to programming in .Net languages.&lt;br /&gt;&lt;br /&gt;Its also very easy to miss them when you switch to other languages that do (or did) not support formal properties.  Take Objective-C, for instance.  It has been knighted by Apple as the "core" language of the Mac OS platform, and has been fairly well regarded by folks who can get past its lack of Namespace support and its rather odd method call syntax.  It pretty fast and if Obj-C doesn't have the features you need, you can simply include a regular, run-of-the-mill C or C++ header file, and continue on your way.  What it didn't have before Objective-C Version 2.0 was &lt;/span&gt;&lt;span style="font-style:italic;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Formal Properties&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;.&lt;br /&gt;&lt;br /&gt;You can't possibly believe the ruckus adding formal properties caused in the Objective-C community.  It would have been similar to putting a directive in C# called #SCREW_STRICT_TYPING (which I personally thing should happen) to turn on dynamic language-style late binding.  The whole thing is, now you can get the Obj-C preprocessor to synthesize properties for you, much like with C#'s oh-so-sweet automatic properties.  That isn't what ticked off the purists, though.  They changed the syntax for accessing properties.  It used to work like this:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;MyWonderfulClass *wonderfulClass = [[[MyWonderfulClass alloc] init] autorelease];&lt;br /&gt;&lt;br /&gt;//Set a property here.&lt;br /&gt;[wonderfulClass setCoolProperty: @"Valuable Data"];&lt;br /&gt;//Get a property value here.&lt;br /&gt;NSString *data = [wonderfulClass coolProperty];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;And that still works great, &lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;if you know the pattern&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;. If you created getters/setters and didn't follow the pattern, the development tools wouldn't see your properties.  The new syntax in Obj-C looks just like it does in C# or VB.  You access the properties like this:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;MyWonderfulClass *wonderfulClass = [[[MyWonderfultClass alloc] init] autorelease];&lt;br /&gt;&lt;br /&gt;//Set a property here.&lt;br /&gt;wonderfulClass.CoolProperty = @"Valuable Data";&lt;br /&gt;//Get a property here.&lt;br /&gt;NSString *data = wonderfulClass.CoolProperty;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;And that is what caused all the fuss.  Some folks though it was too...C#-ish, others just thought it was ugly, and out of character for the Objective-C language.  Some thought it was great, because they didn't have to type square brackets for properties anymore.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Now, for those of you who are more C#-ish and don't really understand all of the Objective-C square-bracket mania, I'll give you the short C# low-down.  The first line in the code samples is similar to saying this in C#:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using(MyWonderfulClass wonderfulClass = new MyWonderfulClass())&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Specifically, the square brackets indicate the Objective-C equivalent of a function call in C#, except Objective-C doesn't do direct function calls on its own objects.  It will for ANSI C functions and C++ functions, but Objective-C objects are special.  Objective-C &lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;sends a message&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; to the object and the object responds.  I thought that was all conceptual mumbo-jumbo when I was first learning it, but as it turns out, it really does send messages to the objects and the objects respond.  If you want to know more about how Objective-C works, see &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Objective-c"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;this&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; article on Wikipedia, and if that really isn't enough for you, see &lt;/span&gt;&lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/chapter_1_section_1.html"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;theauthoritative source&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; at Apple's developer network site.&lt;br /&gt;&lt;br /&gt;Now, back to properties.  In the Java world, they do what they did in old-school Objective-C (and C++ before that).  Specifically, for properties you should follow a pattern for your getter/setter functions.  In Java parlance, it is called Bean pattern.  And just like everything Java, the documentation makes it out to be a whole lot more complicated than it really is.  It works by defining the expected signatures for "property" getter and "property" setter functions so tools like IDE's can figure out what the heck you're doing.  The problem with that approach, as far as I can see, is that if you don't know about the pattern, you are going to be frustrated with it until you either figure out what that pattern is, or see Eclipse or NetBeans do it for you, and if you see the IDE do it for you, you may not understand &lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;why&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; it does things that way, which I consider to be a distinct problem.&lt;br /&gt;&lt;br /&gt;Contrast to VB, C#, and now Objective-C, where you have the pattern hard-wired into the language.  You know what a property is when you glance at it (in VB because it has the Captain Obvious keyword of PROPERTY plastered all over it).  Formal property support is even engrained into the CLR itself.  All you have to do is look at how you pull properties out of an unknown object to see how very formalized properties are in the .Net world.&lt;br /&gt;&lt;br /&gt;Basically, the philosophical difference between formal and informal properties is the same philosophical debate that Ruby on Rails and subsequently ASP.Net MVC brings to the world of web development.  Do you like Convention over Configuration?  Do you prefer formalized, compiler checkable specifications?&lt;br /&gt;&lt;br /&gt;Personally, I prefer formal properties the way they are implemented in .Net over what Java uses, because I can save myself some icky-looking parens when I chain together property-gets and method on the ends of properties, but that is, admittedly trivial and wouldn't stop me from using Java if I thought it had a clear advantage over .Net for development.  The best way to decide, is of course, to use the different languages and make the choice for yourself.&lt;br /&gt;&lt;br /&gt;Have fun coding!&lt;/span&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2008/10/formal-properties.html';reddit_title='Formal Properties';digg_url='http://vampirebasic.blogspot.com/2008/10/formal-properties.html';digg_title='Formal Properties';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-381665391120704134?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/381665391120704134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2008/10/formal-properties.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/381665391120704134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/381665391120704134'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2008/10/formal-properties.html' title='Formal Properties'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-3058075398809711121</id><published>2008-09-30T09:52:00.010-05:00</published><updated>2008-10-02T08:55:57.456-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Development'/><category scheme='http://www.blogger.com/atom/ns#' term='VB'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>Language of Choice</title><content type='html'>Visual Basic used to be the red-headed stepchild of the Microsoft world.  It was the language we all loved to hate.  It had enough &lt;a href="http://www.catb.org/jargon/html/B/bondage-and-discipline-language.html"&gt;bondage and discipline&lt;/a&gt; (you can't put parenthesis on a Sub invocation unless you put the Call keyword in front of it...WTF?) in the days of VB6 and lacked enough performance and advanced features that it basically wore a sandwich board with a target painted on it.&lt;br /&gt;&lt;br /&gt;Then along came the CLR, and the .Net label was affixed to VB.  Gone were the B&amp;amp;D features (Get/Set/Let for properties?  WTF?).  Gone was the mediocre performance.  Gone was the love.  Even though VB 7 became what Borland &lt;span style="font-style: italic;"&gt;wished&lt;/span&gt; Delphi could have been, an easy-to-read language that eschewed some of the more...dangerous features of the C-derived languages whilst giving the developer enough room to be creative, and enough performance to avoid new hardware purchases, many developers think the language is total, utter crap.&lt;br /&gt;&lt;br /&gt;The sad fact of the matter is, LoC is many times an emotional decision.  Developers love to hate VB (or Java for that matter) because of its un-hipness.  They hate being mocked because language X doesn't have wicked cool feature Y.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;blockquote&gt;Dev A: You use &lt;span style="font-style: italic;"&gt;What&lt;/span&gt;?  It has no clojures.  It sucks.&lt;br /&gt;Dev B: WTF?  I don't know what a clojure is, and I probably don't need it.&lt;br /&gt;Dev A: [Emits toxic levels of Smug]&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This doesn't excuse you from knowing which languages are capable of what features.  You never know what feature you could use to save your company cash and make you look like a wizard.&lt;br /&gt;&lt;br /&gt;For example, see C# run straight into a brick wall with this bit of love:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;&lt;br /&gt;object listOfCritters;&lt;br /&gt;if(gimmieHTML)&lt;br /&gt;{&lt;br /&gt;listOfCritters = GetArrayOfLions();&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;listOfCritters = GetArrayOfMonkies();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;foreach(var animal in listOfCritters)&lt;br /&gt;{&lt;br /&gt;if(animal.TypeName = "Monkey")&lt;br /&gt;animal.FlingPoo();&lt;br /&gt;else&lt;br /&gt;animal.PreyUponGazelle();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;/pre&gt;&lt;/blockquote&gt;Obviously, this won't work in C#.  The compiler will verbally abuse you for trying to make some undefined, random call on some untyped, random, unknown object.  This never really made much sense to me, because the runtime engine will know what type it is, and if you write good unit tests, you'll know well before deployment if you're code is bonkers or not, but it is what it is.&lt;br /&gt;&lt;br /&gt;Next, in VB:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;...&lt;br /&gt;Dim listOfCritters&lt;br /&gt;If gimmieHTML Then&lt;br /&gt;listOfCritters = GetArrayOfLions()&lt;br /&gt;Else&lt;br /&gt;listOfCritters = GetArrayOfMonkies()&lt;br /&gt;End If&lt;br /&gt;&lt;br /&gt;For Each animal in listOfCritters&lt;br /&gt;If animal.TypeName = "Monkey"&lt;br /&gt;animal.FlingPoo()&lt;br /&gt;Else&lt;br /&gt;animal.PreyUponGazelle()&lt;br /&gt;Next&lt;br /&gt;&lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;This is contrived, of course. For a realistic example, in &lt;a href="http://msdn.microsoft.com/en-us/library/ms162169.aspx"&gt;SMO&lt;/a&gt;, the authors attached the Name property to table objects, stored procedure objects, view objects, etc, &lt;span style="font-style: italic;"&gt;at the final object level.&lt;/span&gt; If you get a list of "Database objects"(I don't remember what their base class really is), with tables and sproc's and what-have-you all mixed in together, there is no interface to fall back to to make accessing the Name property generic.&lt;br /&gt;&lt;br /&gt;Point being, know which languages have which features.  Don't be afraid to learn all 3 of the .Net biggies (VB, C#, C++/CLI).  With the economy getting soft and flabby around the middle, it may make the difference between you paying the rent and paying the unemployment office a visit.&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;reddit_url='http://vampirebasic.blogspot.com/2008/09/language-of-choice.html';reddit_title='Language of Choice';digg_url='http://vampirebasic.blogspot.com/2008/09/language-of-choice.html';digg_title='Language of Choice';digg_topic='programming';digg_skin='compact';digg_window='new';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt; &lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-3058075398809711121?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/3058075398809711121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2008/09/language-of-choice.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3058075398809711121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/3058075398809711121'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2008/09/language-of-choice.html' title='Language of Choice'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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-282487425534208111.post-880020605594050562</id><published>2008-09-22T08:31:00.003-05:00</published><updated>2008-09-23T08:43:49.106-05:00</updated><title type='text'>Sub Main()</title><content type='html'>Vampire Basic - this name is the result of a joke about a throw-away utility I once wrote in VB.Net on a project that was entirely C#.  For whatever reason, I had come in early and had left the lights off in the office, so when the next person came in and saw it was VB, I told them that I was coding in the dark so it wouldn't die from exposure to the light, like a vampire.&lt;br /&gt;&lt;br /&gt;In this blog, I will address thoughts and issues covering multiple platforms and multiple languages including C, Obj-C, Java, C#, and of course, Vampire Basic.Net.  The first post with real, usable content should appear about one week from now.  I haven't decided exactly where I am going to start, but one of my goals is to promote expanding skill sets across language and even platform boundaries.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/282487425534208111-880020605594050562?l=vampirebasic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vampirebasic.blogspot.com/feeds/880020605594050562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://vampirebasic.blogspot.com/2008/09/sub-main.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/880020605594050562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/282487425534208111/posts/default/880020605594050562'/><link rel='alternate' type='text/html' href='http://vampirebasic.blogspot.com/2008/09/sub-main.html' title='Sub Main()'/><author><name>NTC</name><uri>http://www.blogger.com/profile/17998164593896115532</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>1</thr:total></entry></feed>
