<?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-3373750351646461251</id><updated>2011-09-19T08:46:38.570-07:00</updated><category term='xml'/><category term='system.io'/><category term='jQuery'/><category term='introduction'/><category term='webforms'/><category term='javascript'/><category term='SQL'/><category term='dotnet'/><category term='start here'/><category term='urlrouting'/><category term='nhibernate'/><title type='text'>I Sold My Soul to Microsoft</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-3830583526395073697</id><published>2010-12-21T04:07:00.001-08:00</published><updated>2011-09-08T03:46:19.283-07:00</updated><title type='text'>Favourite Geek Jokes</title><content type='html'>Why do programmers get Halloween and Christmas mixed up?&lt;br /&gt;Because Oct 31 = Dec 25&lt;br /&gt;&lt;br /&gt;There are 10 types of people in the world: those who understand binary, and those who don't&lt;br /&gt;&lt;br /&gt;Infinite mathematicians walk into a bar. The first one orders a pint. The second orders half a pint. The third orders a quarter pint. The fourth orders an eighth of a pint. the fifth orders a sixteenth of a pint. The barman sighs, and pours two pints.&lt;br /&gt;&lt;br /&gt;Two hydrogen atoms walk into a bar.&lt;br /&gt;One says, “I think I’ve lost an electron.”&lt;br /&gt;The other says, “Are you sure?”&lt;br /&gt;The first replies, “Yes, I’m positive…”&lt;br /&gt;&lt;br /&gt;A cloud of Argon drifts into a bar. The barman says "Sorry, we don't serve noble gasses in here". The Argon doesn't react.&lt;br /&gt;&lt;br /&gt;Two chemists are working in a lab. One turns to the other and asks "Know any good jokes about Sodium?". The other shakes his head and says "Na".&lt;br /&gt;&lt;br /&gt;Werner Heisenberg is speeding down a highway, when he's pulled over by the police. The cop walks up to him and says, "Excuse me, sir, do you know how fast you were driving?" Heisenberg looks up to the officer and says, "Nope, but I know exactly where I was!"&lt;br /&gt;&lt;br /&gt;A physicist, an engineer and a statistician go hunting. 50m away from them they spot a deer. The physicist calculates the trajectory of the bullet in a vacuum, raises his rifle and shoots. The bullet lands 5m short. The engineer adds a term to account for air resistance, lifts his rifle a little higher and shoots. The bullet lands 5m long. The statistician yells “we got him!”.&lt;br /&gt;&lt;br /&gt;.titanic { float: none; }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-3830583526395073697?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/3830583526395073697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2010/12/stack-trace.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/3830583526395073697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/3830583526395073697'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2010/12/stack-trace.html' title='Favourite Geek Jokes'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-7241101328348753410</id><published>2010-10-15T03:18:00.000-07:00</published><updated>2010-10-15T03:31:06.659-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>JQuery and the update panel</title><content type='html'>If you're new to JQuery you'll no doubt have seen the various samples of code that tell you how to initialize a JQuery function or asset on page load, like this example using a datepicker:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$(function() {&lt;br /&gt;  $( "#datepicker" ).datepicker();&lt;br /&gt; });&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;What they don't tell you is that this doesn't work properly if the page element on which the JQuery is acting is in an Update Panel control. &lt;br /&gt;&lt;br /&gt;Fortunately there's a simple solution. Get a pagerequestmanager first, and use that to call the function. Again, the example is using the datepicker:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;var prm = Sys.WebForms.PageRequestManager.getInstance();&lt;br /&gt;prm.add_pageLoaded(LoadMe); &lt;br /&gt;&lt;br /&gt;function LoadMe() {&lt;br /&gt;  $( "#datepicker" ).datepicker();&lt;br /&gt; });&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-7241101328348753410?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/7241101328348753410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2010/10/jquery-and-update-panel.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/7241101328348753410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/7241101328348753410'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2010/10/jquery-and-update-panel.html' title='JQuery and the update panel'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-7629837649848742968</id><published>2010-05-12T08:23:00.000-07:00</published><updated>2010-05-12T08:51:58.436-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dotnet'/><title type='text'>Bit Field Enumerations</title><content type='html'>I learned a neat trick today which allows you to store multiple values in a single database field by linking it to an enumeration. &lt;br /&gt;&lt;br /&gt;The programming construct behind the idea is called a Bit Field. It's simple, really. An enumeration is basically just a list of numeric values linked to text labels, and the usual form is to increase the numeric values incrementally, so ...&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Public Enum ColoursEnum &lt;br /&gt;    Clear = 0&lt;br /&gt;    Red = 1&lt;br /&gt;    Blue = 2&lt;br /&gt;    Green = 3&lt;br /&gt;    Yellow = 4&lt;br /&gt;    Purple = 5&lt;br /&gt;End Enum&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;But what if, instead of assigning your numeric values incrementally you decide to double them up each time, creating a number series which can be represeted by a bit:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Public Enum ColoursEnum  &lt;br /&gt;    Clear = 0&lt;br /&gt;    Red = 1&lt;br /&gt;    Blue = 2&lt;br /&gt;    Green = 4&lt;br /&gt;    Yellow = 8&lt;br /&gt;    Purple = 16&lt;br /&gt;End Enum&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Looks a bit odd, no? Well whilst it does *look* odd you can do something clever with this series of values: the gap between each one means that if you wanted to, say, have an Enum with &lt;i&gt;more than one value&lt;/i&gt; each potential value has a unique numeric identifier created by adding the values together. A numeric value of 12, in the above example, can only be made up by adding Green and Yellow. A numeric value of 19 can only be reached by adding Red, Blue and Purple. A numeric value of 2 can only be reached if the Enum is Blue and Blue alone. &lt;br /&gt;&lt;br /&gt;So if you create a single database field to hold a single int, by making it a bitwise field you can make it hold more than one value. This has a multitude of uses: I came across it whilst trying to create a "status" column for a database object that could in fact have more than one status at once. Rather than the ugly approach of creating a boolean column for each potential status, I can have a single status column, link it to an Enum and have a bit field join to make it hold multiple values. Neat!&lt;br /&gt;&lt;br /&gt;Be aware that in such an enumeration the "zero" value has to be unique - it can't be a part of any other combination of numbers. So you need to assign zero a value and it needs to be some sort of "resting" value indicating the enumeration is effectively empty - even if that means linking it to a text flag like "empty" or "not set".&lt;br /&gt;&lt;br /&gt;However you may think you've spotted a flaw here: am I not going to have to introduce some slightly annoying and convoluted logic somewhere to take the value from the database, look at the enumeration and decide what set of values my field is actually holding? Thankfully the .net framework automates all of this for us.&lt;br /&gt;&lt;br /&gt;All you have to do is add a Flags attribute to the enum:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;Flags()&gt; _&lt;br /&gt;Public Enum ColoursEnum &lt;br /&gt;    Clear = 0&lt;br /&gt;    Red = 1&lt;br /&gt;    Blue = 2&lt;br /&gt;    Green = 4&lt;br /&gt;    Yellow = 8&lt;br /&gt;    Purple = 16&lt;br /&gt;End Enum&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And .Net does all the work for you. It's slightly different in C# by the look of things: you need to use [FlagsAttribute] instead of &lt;Flags()&gt; but the end result is the same.&lt;br /&gt;&lt;br /&gt;.Net will now treat each potential set of values from this enumeration differently. That is to say that if you loop through all the potential values of Colours above you'll get separate entries for Red, RedBlue, RedBlueGreen, RedGreen and so on. &lt;br /&gt;&lt;br /&gt;You can also set your Enum to hold multiple values by using a bitwise "OR" operator (a pipe |):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim myRed as ColoursEnum = ColoursEnum.Red&lt;br /&gt;Dim myBrown As ColoursEnum = ColoursEnum.Red | ColoursEnum.Purple&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And in the same manner you can use a bitwise "AND" operator (an ampersand &amp;) to isolate a single value and check it. Colours are a bad way of demonstrating this but hopefully the logic will read through.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim myBrown As ColoursEnum = ColoursEnum.Red | ColoursEnum.Purple&lt;br /&gt;&lt;br /&gt;Dim myRed As ColoursEnum = myBrown &amp; ColoursEnum.Red&lt;br /&gt;'This will set MyRed equal to Red, since it matches something in the enum&lt;br /&gt;Dim noColour As ColoursEnum = myBrown &amp; ColoursEnum.Green&lt;br /&gt;'This will set noColour equal to Clear since green doesn't match anything in the enum&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-7629837649848742968?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/7629837649848742968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2010/05/bit-field-enumerations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/7629837649848742968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/7629837649848742968'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2010/05/bit-field-enumerations.html' title='Bit Field Enumerations'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-2654303057991101654</id><published>2010-02-19T04:03:00.000-08:00</published><updated>2010-02-19T04:29:50.795-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webforms'/><category scheme='http://www.blogger.com/atom/ns#' term='urlrouting'/><category scheme='http://www.blogger.com/atom/ns#' term='dotnet'/><title type='text'>URL Routing Niggles</title><content type='html'>I've been playing with URL re-routing in Web Forms recently. Although originally supplied as part of the MVC framework the classes can now be used in standard web forms so you can have nice, neat, copy-and-paste friendly, search engine optimised URLs in your web forms application.&lt;br /&gt;&lt;br /&gt;The basics of how to do this are well documented, so I won't bore you with them. If you don't know how it's done, I'll let &lt;a href="http://www.4guysfromrolla.com/articles/012710-1.aspx" target="_blank"&gt;4-Guys&lt;/a&gt; bore you instead.&lt;br /&gt;&lt;br /&gt;Trying to implement it I ran into a couple of small hurdles though, which I thought I'd document for reference. It's a little embarrassing really because both of these things are quite clear if you read the documentation properly instead of skimming and getting down to trying it out.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Optional &amp; Extensible Parameters&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The first is how to make parameters optional. Let's say for example that I have a search function with two parameters: firstname and surname. I might want the url for that search function to look like this:&lt;br /&gt;/people/search/(searched text for firstname)/(searched text for surname)/&lt;br /&gt;Let's further assume that I have various other pages I want to map inside the people folder, so things like:&lt;br /&gt;/people/summary/&lt;br /&gt;/people/management/&lt;br /&gt;&lt;br /&gt;So I define my virtual URL like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim urlPattern As String = "people/{action}/{firstname}/{surname}"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And as soon as I do that, /people/summary/ fails. It's expecting a firstname and a surname as part of the URL and doesn't recognise the address.&lt;br /&gt;&lt;br /&gt;To solve thisWe add a dictionary to the route value, like so:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;reportRoute = New Route(urlPattern, New ReportRouteHandler)&lt;br /&gt;reportRoute.Defaults = New RouteValueDictionary(New With {.firstname = "", .surname = ""})&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This instructs the route that the firstname and surname parameters can be replaced with a default - in this case an empty string - if they're missing. And of course this being a dictionary you can add as many key/value pairs as you need.&lt;br /&gt;&lt;br /&gt;But there's still one more thing. What if we might want to include some additional information in that URL, or even just make sure that longer URLs fail gracefully? At the moment /people/search/matt/j/thrower/ will fail. To solve this, add an asterisk to the final part of your virtual URL:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim urlPattern As String = "people/{action}/{firstname}/{*surname}"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And voilà! The * indicates that the final parameter is extensible and can be of any length.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Getting Values from Parameters in Target Pages&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The other thing that you'll probably want to do with this is to have a target page read the items in the url parameter collection. Right now you can access the values in {action}, {firstname}, {lastname} and so on inside route handling functions, but the target web form won't know about them. &lt;br /&gt;&lt;br /&gt;My first approach to this was to change the parameters into querystrings and include them in the redirect part of the route handler:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim handlerUrl As String&lt;br /&gt;Dim hand As Web.IHttpHandler&lt;br /&gt;Select Case CStr(routeData.Values("action")).ToLower()&lt;br /&gt;    Case "search"&lt;br /&gt;        handlerUrl = String.Format("/people/search.aspx?firstname={0}&amp;surname={1}", routeData.Values("firstname"), routeData.Values("surname"))&lt;br /&gt;End Case&lt;br /&gt;&lt;br /&gt;hand = DirectCast(System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(handlerUrl, GetType(Web.UI.Page)), Web.IHttpHandler)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Which blows up in your face because the querystring isn't a valid virtual path.&lt;br /&gt;&lt;br /&gt;The way round this is to utilise a handy collection in HttpContext called Items, which allows you to store key/value pairs of data:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim handlerUrl As String&lt;br /&gt;Dim hand As Web.IHttpHandler&lt;br /&gt;Select Case CStr(routeData.Values("action")).ToLower()&lt;br /&gt;    Case "search"&lt;br /&gt;        handlerUrl = "/people/search.aspx"&lt;br /&gt;        For Each urlParm In requestContext.RouteData.Values&lt;br /&gt;            requestContext.HttpContext.Items(urlParm.Key) = urlParm.Value&lt;br /&gt;        Next&lt;br /&gt;End Case&lt;br /&gt;&lt;br /&gt;hand = DirectCast(System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(handlerUrl, GetType(Web.UI.Page)), Web.IHttpHandler)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And you can pick these up in your target page like so:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim firstname As String = HttpContext.Current.Items("firstname").ToString&lt;br /&gt;Dim surname As String = HttpContext.Current.Items("surname").ToString&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-2654303057991101654?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/2654303057991101654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2010/02/ur-routing-niggles.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/2654303057991101654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/2654303057991101654'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2010/02/ur-routing-niggles.html' title='URL Routing Niggles'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-8103141740888637590</id><published>2010-02-12T08:28:00.000-08:00</published><updated>2010-02-12T08:39:16.935-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nhibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='dotnet'/><title type='text'>Quey across a join in nHibernate</title><content type='html'>My god, I don't think I've ever come across any framework with quite such a poor popularity-to-documentation framework as Fluent nHibernate. Everyone is using it, &lt;span style="font-style:italic;"&gt;but no one writes down how&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Stupid nHibernate.&lt;br /&gt;&lt;br /&gt;So, after spending ages trying to get something as simple as a rowcount, today I have spent an equally frustrating period trying to get a results set which does a logic OR operation across a joined table. Something as petty as this, in SQL terms:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;SELECT * from product p&lt;br /&gt;    inner join sku s on s.id = p.id&lt;br /&gt;    WHERE p.Name like '%widget%' &lt;br /&gt;    OR s.SkuCode like '%wd_%'&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The issue arises because even though my mappings are correct, nHibernate throws a wobbler at you if you start with Product and try and get it to recognise that it should be able to filter on a field in the joined sku table. This, for example, compiles but fails horribly even though to my mind it's the intuitive way of presenting the above query in nHibernate:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;        Dim results As ArrayList = session.CreateCriteria(Of DataTransferObjects.Product) _&lt;br /&gt;            .Add(Expression.Or( _&lt;br /&gt;            Expression.Like("Name", "widget"), _&lt;br /&gt;            Expression.Like("SkuCode", "wd_"))) _&lt;br /&gt;        .List()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;No, what you have to do is set up a CreateAlias to the table and use that:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;        Dim results As ArrayList = session.CreateCriteria(Of DataTransferObjects.Product) _&lt;br /&gt;            .CreateAlias("Skus", "sku") _&lt;br /&gt;            .Add(Expression.Or( _&lt;br /&gt;            Expression.Like("Name", "widget"), _&lt;br /&gt;            Expression.Like("sku.SkuCode", "wd_"))) _&lt;br /&gt;        .List()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Certainly not the way I'd expect a "highly intuitive", productivity-enhancing framework to function. Not by a long shot.&lt;br /&gt;&lt;br /&gt;I could have done the required work by creating a couple of custom data handling objects and accompanying T-SQL stored procedures in about ten minutes. To do the same thing in nHibernate has taken two days. What's that about enhancing productivity?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-8103141740888637590?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/8103141740888637590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2010/02/quey-across-join-in-nhibernate.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/8103141740888637590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/8103141740888637590'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2010/02/quey-across-join-in-nhibernate.html' title='Quey across a join in nHibernate'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-6216993462958493665</id><published>2010-02-12T02:11:00.001-08:00</published><updated>2010-02-12T02:22:18.905-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nhibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='dotnet'/><title type='text'>nHibernate Projections in VB.net</title><content type='html'>Well, this has lead me a merry dance, I can assure you. You'd think it was pretty straightforward to do something as simple as a row count in nHibernate, wouldn't you? Well, in point of fact it actually is pretty simple but it's just not well documented anywhere. Particularly perplexing is the fact that most of the examples seem to have been ripped straight from the &lt;span style="font-style: italic;"&gt;Java&lt;/span&gt; hibernate implementation and I'm not entirely sure this will even port to C# and work, let alone translate to VB (I haven't tried in C#).&lt;br /&gt;&lt;br /&gt;Anyway, just in case some poor soul has the same problem and gets stuck, this is how you do it:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Dim pResults As IList = session.CreateCriteria(GetType(dto.Product)) _&lt;br /&gt;.SetProjection(Projections.RowCount()).List()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Of course "dto.Product" is a custom class I'm using that's specific to what I'm trying to do, so stick your own in there and you should be good to go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-6216993462958493665?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/6216993462958493665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2010/02/nhibernate-projections-in-vbnet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/6216993462958493665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/6216993462958493665'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2010/02/nhibernate-projections-in-vbnet.html' title='nHibernate Projections in VB.net'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-1036291899243425503</id><published>2009-03-31T03:16:00.000-07:00</published><updated>2009-03-31T03:24:03.056-07:00</updated><title type='text'>Date Conversions in SQL</title><content type='html'>Does what it says on the tin. I find this a particularly handy trick to know when trying to copy &amp; paste SQL data from Query Analyser into Excel, because the default date/time format causes Excel to scramble the dates into nonsense.&lt;br /&gt;&lt;br /&gt;Stupid Excel.&lt;br /&gt;&lt;br /&gt;Anyway, on with the show.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;CONVERT(CHAR(19),GETDATE()) -- gives 31 March 2003 11:19&lt;br /&gt;CONVERT(CHAR(11),GETDATE(),106) -- gives 31 March 2003&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-1036291899243425503?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/1036291899243425503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/03/date-conversions-in-sql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/1036291899243425503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/1036291899243425503'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/03/date-conversions-in-sql.html' title='Date Conversions in SQL'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-4272570223658708232</id><published>2009-03-12T07:59:00.000-07:00</published><updated>2009-03-12T08:03:18.504-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>A SQL Split function</title><content type='html'>This is so useful it's beyond me why it isn't adopted as standard functionality. Maybe it is in SQL Server 2008. In the meantime, here's how I do it.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;CREATE     FUNCTION fnSplit(@Data nvarchar(4000), &lt;br /&gt;@Delimiter varchar(10) = ',')&lt;br /&gt;RETURNS @tblSplit TABLE &lt;br /&gt;&lt;br /&gt;(ItemId int IDENTITY(1, 1) NOT NULL PRIMARY KEY,&lt;br /&gt;Item nvarchar(4000) NULL)&lt;br /&gt;&lt;br /&gt;AS&lt;br /&gt;&lt;br /&gt;BEGIN&lt;br /&gt;&lt;br /&gt;DECLARE @Delimiter2 varchar(12),&lt;br /&gt;                @item nvarchar(4000),&lt;br /&gt;                @iPos int,&lt;br /&gt;                @DelimWidth int&lt;br /&gt;&lt;br /&gt;--had to do this cuz if they send in a &gt; 9 char delimiter I could not pre and post append the % wildcards&lt;br /&gt;SET @Delimiter2 = @Delimiter &lt;br /&gt;SET @Delimiter2 = ISNULL(@Delimiter2, ',')&lt;br /&gt;SET @DelimWidth = LEN(@Delimiter2) &lt;br /&gt;&lt;br /&gt;IF RIGHT(RTRIM(@Data), 1) &lt;&gt; @Delimiter2      &lt;br /&gt;                SELECT @Data = RTRIM(@Data) + @Delimiter2&lt;br /&gt;&lt;br /&gt;IF LEFT(@Delimiter2, 1) &lt;&gt; '%' &lt;br /&gt;                SET @Delimiter2 = '%' + @Delimiter2&lt;br /&gt;&lt;br /&gt;IF RIGHT(@Delimiter2, 1) &lt;&gt; '%' &lt;br /&gt;                SET @Delimiter2 = @Delimiter2 + '%'&lt;br /&gt;&lt;br /&gt;SELECT @iPos = PATINDEX(@Delimiter2, @Data) &lt;br /&gt;&lt;br /&gt;WHILE @iPos &gt; 0&lt;br /&gt;BEGIN &lt;br /&gt;                SELECT @item = LTRIM(RTRIM(LEFT(@Data, @iPos - 1)))&lt;br /&gt;                IF @@ERROR &lt;&gt; 0 BREAK&lt;br /&gt;                SELECT @Data =  RIGHT(@Data, LEN(@Data) - (LEN(@item) + @DelimWidth))&lt;br /&gt;                IF @@ERROR &lt;&gt; 0 BREAK&lt;br /&gt;                INSERT INTO @tblSplit VALUES(@item)&lt;br /&gt;                IF @@ERROR &lt;&gt; 0 BREAK&lt;br /&gt;                SELECT @iPos = PATINDEX(@Delimiter2, @Data) &lt;br /&gt;                IF @@ERROR &lt;&gt; 0 BREAK&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;RETURN &lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You call it like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;select item from [reference]..fnSplit( @variable, ',' )&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Where @variable is a varchar containing your comma-delineated string. Useful for sticking directly into IN clauses.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-4272570223658708232?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/4272570223658708232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/03/sql-split-function.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/4272570223658708232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/4272570223658708232'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/03/sql-split-function.html' title='A SQL Split function'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-5988626215239834490</id><published>2009-03-10T07:53:00.000-07:00</published><updated>2009-03-10T07:57:04.266-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='dotnet'/><title type='text'>Reading XML with XPath</title><content type='html'>There's more than one way to read an XML file in dot net, but the XPath model doesn't seem to be terribly widely documented. Which is a shame because although it's a little unintuitive, it offers some functionality that doesn't come with other tools. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;using System.Xml.XPath;&lt;br /&gt;&lt;br /&gt;XPathDocument xDoc = new XPathDocument(“filepath”);&lt;br /&gt;XPathNavigator xNav = xDoc.CreateNavigator();&lt;br /&gt;&lt;br /&gt;Xnav.MoveToRoot();&lt;br /&gt;Xnav.MoveToFirstChild();&lt;br /&gt;&lt;br /&gt;do&lt;br /&gt;{&lt;br /&gt;    //do stuff .. like xNav.GetAttribute(""AttributeName", "");&lt;br /&gt;}&lt;br /&gt;while (Xnav.MoveToNext());&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So, load your xml file by replacing "filepath" with the path of the - ahem - file you want to load. MoveToRoot and MoveToFirstChild do exactly what you'd expect them to, and you can obviously vary these commands depending on where you want to start reading. Then the do-while loop should pass through each node in turn, allowing you to access its attributes and such.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-5988626215239834490?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/5988626215239834490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/03/reading-xml-with-xpath.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/5988626215239834490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/5988626215239834490'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/03/reading-xml-with-xpath.html' title='Reading XML with XPath'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-2085409318679482765</id><published>2009-03-09T07:03:00.000-07:00</published><updated>2009-03-09T07:09:43.998-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>SQL Cursors</title><content type='html'>SQL cursors, for those who don't know, are effectively a way of introducing a loop into a chunk of SQL code. Quite why the people who invented SQL couldn't call them "loops" I don't know - DBAs always have to be different, I suppose. Anyway it's a handy thing to know.&lt;br /&gt;&lt;br /&gt;Beware though that SQL cursors are resource-intensive. If efficiency at the database end is important to you, it might be better to return the data and loop through it in the handling code. However, there are times when you need to get data, loop through it and then do something else at the DB end with the results of the loop. In those cases using a cursor is likely to be less intensive than the round trips involved in two separate back-and-forth trips to the database server.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Declare c1 cursor read_only&lt;br /&gt;For&lt;br /&gt; Select &lt;whatever&gt; from &lt;wherever&gt;&lt;br /&gt;-- select statement picks up &lt;br /&gt;--rows to sort through&lt;br /&gt;&lt;br /&gt;Declare @trackingID int&lt;br /&gt;-- declare a variable to hold the primary key &lt;br /&gt;-- of the rows you’re returning&lt;br /&gt;&lt;br /&gt;Open c1&lt;br /&gt;&lt;br /&gt;Fetch next from c1 into @trackingID&lt;br /&gt;&lt;br /&gt;While @@fetch_status = 0&lt;br /&gt;Begin&lt;br /&gt;--do something with the tracking variable, &lt;br /&gt;--such as using it to select some &lt;br /&gt;--data or do an update or somesuch&lt;br /&gt;&lt;br /&gt; Fetch next from c1 into @trackingID&lt;br /&gt;End&lt;br /&gt;&lt;br /&gt;Close c1&lt;br /&gt;Deallocate c1&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-2085409318679482765?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/2085409318679482765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/03/sql-cursors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/2085409318679482765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/2085409318679482765'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/03/sql-cursors.html' title='SQL Cursors'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-1033027690375471114</id><published>2009-03-03T02:18:00.000-08:00</published><updated>2009-03-03T02:22:40.483-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system.io'/><category scheme='http://www.blogger.com/atom/ns#' term='dotnet'/><title type='text'>Writing files to disc</title><content type='html'>This is a simple enough procedure but, in honesty, I always, always forget how to do it, and when you go and look it up on the interweb it seems that the examples provided are far more complicated than they really need to be. I guess it must be that the System.IO namespace simply isn't as intuitive as perhaps it should be. So here's the stripped down, basic code you need to write a file to disc - don't forget that the namespace goes at the top of your file, while the actual operational code goes inside it.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;using System.IO;&lt;br /&gt;&lt;br /&gt;FileStream myStream = new FileStream("insert File path here", FileMode.Create);&lt;br /&gt;StreamWriter myWriter = new StreamWriter(myStream);&lt;br /&gt;&lt;br /&gt;myWriter.Write("Some Text");&lt;br /&gt;myWriter.Write(Environment.NewLine); &lt;br /&gt;//this creates a new line. Duh!&lt;br /&gt;&lt;br /&gt;myWriter.Close();&lt;br /&gt;myStream.Close();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So put the target path into "insert File path here" and put your text into where it says "some text". Obviously you can keep adding as much text or new lines as you need.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-1033027690375471114?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/1033027690375471114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/03/writing-files-to-disc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/1033027690375471114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/1033027690375471114'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/03/writing-files-to-disc.html' title='Writing files to disc'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-6309496357752445835</id><published>2009-02-27T03:30:00.000-08:00</published><updated>2009-03-03T02:23:06.286-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Finding start of week in T-SQL</title><content type='html'>&lt;p&gt;Wah! So, the first two posts turn out to be HTML posts! Well, probably because I'm not doing much actual dot net programming right now :). Besides, this was too neat not to document. It's a line of SQL commands which will determine the first day of the current week. Could be extended to find the first day of any given week.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;declare @weekStart datetime&lt;br /&gt;select @weekStart = dateadd(dd, (datepart(dw, GetDate()) * -1) + 2, GetDate())&lt;br /&gt;select @weekstart&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You can also put some more jiggery-pokery round it in order to get midnight on the first day of the week:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;declare @weekStart datetime, @now datetime&lt;br /&gt;select @weekStart = dateadd(dd, 0, datediff(dd, 0,  dateadd(dd, (datepart(dw, GetDate()) * -1) + 2, GetDate())))&lt;br /&gt;select @weekstart&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-6309496357752445835?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/6309496357752445835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/02/finding-start-of-week-in-t-sql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/6309496357752445835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/6309496357752445835'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/02/finding-start-of-week-in-t-sql.html' title='Finding start of week in T-SQL'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-7866568800610697563</id><published>2009-02-26T01:57:00.000-08:00</published><updated>2009-02-26T02:01:52.957-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Search Stored Procedures in T-SQL</title><content type='html'>&lt;p&gt;So, I started a blog called "dot net notes" and my first post is about SQL. Doesn't look good but in honesty this is one of the most useful things I ever learned in SQL - how to do a blanket search of the text in all the stored procedures in a given database.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;  &lt;code&gt;SELECT Distinct SO.Name&lt;br /&gt;  FROM sysobjects SO (NOLOCK)&lt;br /&gt;  INNER JOIN syscomments SC (NOLOCK) on SO.Id = SC.ID&lt;br /&gt;  AND SO.Type = 'P'&lt;br /&gt;  AND SC.Text LIKE '%text_to_search_for%'&lt;br /&gt;  ORDER BY SO.Name&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Just replace "text_to_search_for" with, well, whatever you want to search for and you're good to go. Immensely helpful for tracking down chains of stored procedures which call each other, or examples of something you've done before in SQL but can't quite remember, or finding all the SP's in a database which reference a particular table or field. With enough tweaking it'd probably make you tea in the morning and wipe your arse for you. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-7866568800610697563?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/7866568800610697563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/02/search-stored-procedures-in-t-sql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/7866568800610697563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/7866568800610697563'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/02/search-stored-procedures-in-t-sql.html' title='Search Stored Procedures in T-SQL'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3373750351646461251.post-4105855618331190337</id><published>2009-02-25T02:06:00.000-08:00</published><updated>2009-02-25T02:09:21.218-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='introduction'/><category scheme='http://www.blogger.com/atom/ns#' term='start here'/><title type='text'>Introduction</title><content type='html'>OK, well what's this for? I program for a living - mainly asp dot net, but also SQL and classic asp. For a while now I've been collecting notes on how to do certain things - some neat solutions to problems I've found, some things I come up against time and time again but can never remember how to do, some common "gotchas" I've come up against. &lt;br /&gt;&lt;br /&gt;And I figured I'd move it into a blog.&lt;br /&gt;&lt;br /&gt;Why? Well, partly because it's easier for me to index and find things in a blog format. Partly because it's stuff other people might use. So if you find something useful on here, just enjoy. No need to comment unless I've made a fundamental error :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3373750351646461251-4105855618331190337?l=mattthr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mattthr.blogspot.com/feeds/4105855618331190337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mattthr.blogspot.com/2009/02/introduction.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/4105855618331190337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3373750351646461251/posts/default/4105855618331190337'/><link rel='alternate' type='text/html' href='http://mattthr.blogspot.com/2009/02/introduction.html' title='Introduction'/><author><name>Matt Thrower</name><uri>http://www.blogger.com/profile/04426055092986158446</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://homes.ukoln.ac.uk/~mt275/1bat.jpg'/></author><thr:total>1</thr:total></entry></feed>
