TortoiseSVN: Tweaking the Context Menu; Global Ignore

If you use TortoiseSVN alot like I do, then you’ve probably often wished you could put more frequently used items in the first context menu that comes up when you right click on a file in Windows Explorer. By default only update, commit, and checkout are there. You can choose which items appear in the first menu and which appear in the TortoiseSVN sub-menu by selecting Settings, Look and Feel. There you can check and uncheck items to determine whether or not they are on the sub-menu. I got rid of Checkout and included add, delete, rename, and diff.

Another time saver available in settings is Global Ignore Pattern. Items matching this pattern will automatically be ignored when you commit. I currently have mine set to:

*/[Bb]in [Bb]in */obj obj */[Rr]elease *.user *.suo *.resharper */_ReSharper.* _ReSharper.* *.bak *.dll *.pdb.

Embedded Resource Queries or How to Manage SQL Code in Your .NET Projects

I developed a technique for managing SQL code in my .NET projects using the Embedded Resource “Build Action” back in the .NET 1.0 days that I still use to this day. I’ve been meaning to share this with the world for several years now and I’m finally getting around to it.

The benefits of this technique are many. Your SQL queries are contained in individually-editable, properly-formatted files in your .NET project instead of constructed as nasty concatenated strings in your code.

However, at run-time, you don’t have to worry about distributing extra files with your application, the SQL text is an embedded resource in your executable or class libary. You get the best of both worlds. You have source control diffs available but no additional distribution burden.

Before I go further, let me address the issue of stored procedures. Stored procedures have their place. In the past, I’ve maintained 2000+ line stored procedures. I’m ashamed to admit that I’ve even written some 2000+ line stored procedures back in the heyday of client server. Stored procedures (not 2000+ line long ones, surely) have their place and can be a great way to minimize network round trips. However, for purely select-oriented SQL, I think stored procedures are an unecessary administrative burden on most .NET projects. By using this technique, you never have to worry about your .net code being out of synch with the stored procedure.

Modern database servers cache query plans equally well for parameterized ad hoc queries as they do for stored procedures. As a result, unless you are doing some strange things, you will not find a measurable performance difference between using a stored procedure and the embedded resource technique I am about to demonstrate for select-oriented SQL.

Finally, let me say that if you work in a change management environment where it is easier to recompile stored procedures than it is to push out DLLs, then this technique may not be for you. Also, if you expect your query to be re-used as is by many different types of non .NET clients (for example, an excel spreadsheet or other stored procedures) then you may want to stick with a stored procedure. Keep in mind that you can easily re-use SQL stored as embedded resources in .NET DLLs among different .NET projects.

Many times I find myself in a query tool such as Query Analyzer, SSMS Query Editor, or Oracle SQL Developer iteratively developing a SQL query that returns a single recordset of results. Once I’ve got the query working reasonably, I create a new text object in under a folder named SqlQueries in Visual Studio in my project, rename it to something.sql and paste in the SQL from the query tool unaltered. I then comment out the section at the top of the query that declares the parameter variables (if I’m using SQL server). Notice that I don’t delete them. This allows me to easily run the query in a query tool if I need to refine or debug the query.

Once the file is in the project, you have to set the build action to embedded resource as shown below:

Setting Build Action to Embedded Resource

We need a class that helps us conveniently access our embedded resources. I’ve always used a class with static methods like this one:

public class EmbeddedResource {
	private EmbeddedResource() {

	public static StreamReader GetStream(System.Reflection.Assembly assembly, string name) {
		foreach (string resName in assembly.GetManifestResourceNames()) {
			if (resName.EndsWith(name)) {
				return new System.IO.StreamReader(assembly.GetManifestResourceStream(resName));
		return null;

	public static string GetString(System.Reflection.Assembly assembly, string name) {
		System.IO.StreamReader sr = EmbeddedResource.GetStream(assembly, name);
		string data = sr.ReadToEnd();
		return data;

	public static string GetString(string name)
		return EmbeddedResource.GetString(typeof(EmbeddedResource).Assembly, name);

If I wanted to retreive some embedded sql in a file named SelectOrderWithExpensiveItemInfo.sql under a project directory directory named SqlQueries as a string to a variable named sql I would do this:

string sql = EmbeddedResource.GetString("SqlQueries.SelectOrderWithExpensiveItemInfo.sql");
SqlCommand cmd = new SqlCommand(sql);

You may be wondering about the for each loop inside EmbeddedResource.GetStream. Initially, I specified the whole resource name which included what I assumed was the assembly name at the beginning of the resource specifier. Unfortunately, the default namespace from project properties is what is actually used (at least when I first wrote this way back when). I couldn’t find a reliable way to retreive the default namespace so I added the search logic. Also keep in mind that you can only use GetString without passing the assembly in if your code is executing in the same assembly in which the embedded resource is housed.

That’s all there is to it. Here’s a fully-functional demo solution showing this technique in action using the AdventureWorks database. Enjoy. I hope that you find embedded resource SQL queries as useful as I have.

Windows HTTP Subversion Install

PS (04/04/2009): Just use VisualSVN Server — it takes all the pain out of installation


I wrote this several months ago after spending more time than seemed reasonable getting subversion running.  Enjoy…

 Install Apache 2.0 (not 2.2):
Select public on port 80 option.  If you already have a web server running, you will get an error.  Ignore.
After install completes, Select Program|Apache|Configure|Edit..config
Change Listen 80 to Listen 8080 (or some other port), save, and restart the service using the apache feather icon in the tray
If nothing shows up in tray, run this: “C:\Program Files\Apache Group\Apache2\bin\apache” -k install -n “Apache2” and then you will see it in the tray.
Surf to http://localhost:8081/ to verify apache install

Install Subersion:

Install Tortoise:

Edit httpd.conf again and add this at the end:
<Location /svn>
  DAV svn
  SVNPath C:\SubversionRepo
where /svn is the virtual (web) path you will use to access the repository and C:\SubversionRepo is the local filesystem path to the repository.  Restart the Apache service.

Verify that you can access the repository via http by opening windows explorer, right clicking, selecting TortoiseSVN|Repo-brower.  Type in http://localhost:8080/svn.  Right-click the top level and select Create Folder.  Enter TestApp and press OK.  If the folder creates, everything is working OK.

Now, the final step is to add digest authentication to Apache.  Open httpd.conf and uncomment this line:
LoadModule auth_digest_module modules/
Next, add the following lines (subbing in your own “domain” EG AcmeSoftware) to the <Directory “C:/Program Files/Apache Group/Apache2/htdocs”> secion:
  AuthType Digest
  AuthName “domain”
  AuthDigestFile “C:\Program Files\Apache Group\Apache2\passwd\passwords”
  Require valid-user

Now, you must use the command line to add users and passwords.  First, create the following directory: C:\Program Files\Apache Group\Apache2\passwd.  When adding the first user, run the following:

“C:\Program Files\Apache Group\Apache2\bin\htdigest” -c “C:\Program Files\Apache Group\Apache2\passwd\passwords” domain username

For subsequent users, remove the -c or you will recreate the file and lose the first user already stored in the file.  Now, restart Apache, browse to the repository using TortoiseSVN from Windows Explorer.  You should now be prompted for a user id and password.  Check “save authentication” to avoid being prompted for every access to the repository.  Even after you check this the first time, you will get prompted one more time on your next access to the repository.

You can do everything you need to do to manage the repository via TortoiseSVN.  Don’t get distracted by other things like WebSVN, Cygwin, Ankh (which is slow and buggy) or anything else.  Subversion + TortoiseSVN = complete solution.

If you do not have a static IP and you want to access your repository from remote locations, visit  If you are behind a NAT router, you can probably configure your router to forward all incoming requests on the port you specified in the steps above to a specific private address.  Note that if you are using DHCP to assign IP private addresses to your computers, you will need to reserve a specific private address for the machine hosting SVN.