SQL Server SP2 quirks
Wednesday, February 28, 2007 6:35:40 PM (GMT Standard Time, UTC+00:00)
Ok, as sad as it sounds I've been looking forward to the latest SQL Server service pack since I heard about some of the issues it fixed as there was two "glitches" in particular that seriously bugged me, namely:
- Loading a SQL file into the query editor on a live connection would ask you to log in again -this bugged the hell out of me because I have a number of routines saved on my disk as SQL files that manage client's servers and so I don't always have the password to easily hand which would just delay development (ok all be it by 30seconds or so but that's not the point)
- It would never remember my password in the initial splash screen, again see why above.
Anyway, it's great to see that these two points were fixed as well as a load of other issues but I couldn't help but chuckle when I saw the new context menus, I don't know about you but when editing this table I didn't know which one I needed to choose:

FWIW you need "Design" to open the design view and "Edit" to generate a SQL CREATE Script. Genius!
Employing someone 101
Tuesday, February 27, 2007 9:22:48 AM (GMT Standard Time, UTC+00:00)
Stacey recently wrote an excellent brief on the pro's and con's of employing someone however this morning when I came to post it online I realised that it was deleted when I formatted the laptop for a system demonstration last week. Luckily however I have a hard copy so I'll have it re-typed and put online ASAP.
In the meantime however I shall reflect with this classic (which I’m looking to implement in The Site Doctor ASAP)…
Attire
It is advised that you come to work dressed according to your salary. If we see you wearing Prada sneakers and carrying a Gucci bag, we assume you are doing well financially and therefore you do not need a raise.
If you dress poorly, you need to learn to manage your money better, and therefore you do not need a raise. If you dress in-between, you are right where you need to be and therefore you do not need a raise.
Personal Days
Each employee will receive 104 personal days a year. They are called Saturday and Sunday.
Lunch Break
Skinny people get 30 minutes for lunch as they need to eat more so that they can look healthy.
Normal size people get 15 minutes for lunch to g et a balanced meal to maintain their average figure.
Sick Days
We will no longer accept a doctor statement as proof of sickness. If you are able to go to the doctor, you are able to come to work.
Restroom Use
Entirely too much time is being spent in the restroom. There is now a strict 3-minute time limit in the stalls. At the end of three minutes, an alarm will sound, the toilet paper roll will retract, the stall door will open and a picture will be taken. After your second offence, your picture will be posted on the company bulletin board under the "Chronic Offenders" category.
Surgery
As long as you are an employee here, you need all your organs. You should not consider removing anything. We hired you intact. To have something removed constitutes a breach of employment.
Thank you for your loyalty to our company. We are here to provide a positive employment experience. Therefore, all questions, comments, concerns, complaints, frustrations, irritations, aggravations, insinuations, allegations, accusations, contemplation, consternation and input should be directed to the State Unemployment Offices.
DasBlog RSS Feed Macro
Saturday, February 24, 2007 2:39:04 PM (GMT Standard Time, UTC+00:00)
As part of my blog’s re-design I wanted to integrate my statistics from Last.FM which monitors what music you’re listening to and generates a stack of statistics about your listening habit (see About Last FM for more information).
Anyways, I started writing my own RSS macro when I came across one already developed by John Forsythe (http://www.jforsythe.com/) which did pretty much exactly what I was planning on developing, the only difference though was that his was hard-coded to preset node names whereas I was planning on using an XSL file to format mine to offer maximum flexibility in the long run so I updated his with the use of reflector (thanks to John Forsythe though!!).
There are a couple of difference to note with this code and John Forsythe's:
- The RSS retrieval is no longer handled by an external library -in this instance I wanted to keep this as simple and stand-alone as possible.
- There is no max item count at present -this is mainly because I didn't need it for the Last.FM Feed, I may alter that later.
Source code for a dasBlog XSL based RSS reader
using System;
using System.IO;
using System.Security.Cryptography;
using System.Diagnostics;
using System.Text;
using System.Web;
using System.Web.UI;

using newtelligence.DasBlog.Runtime;
using newtelligence.DasBlog.Web.Core;

namespace TSDMacros
{...}

{
public class TheSiteDoctor
{...}

{
protected SharedBasePage requestPage;
protected Entry currentEntry;

public TheSiteDoctor(SharedBasePage page, Entry entry)
{...}

{

requestPage = page;

currentEntry = entry;

}

/// <summary>
/// A dasBlog macro to retrieve an RSS feed and apply XSL to
/// it before caching it for x minutes
/// </summary>
/// <param name="xslVPath">The virtual path of the XSL file</param>
/// <param name="rssPath">The RSS feed URL</param>
/// <param name="minutesToCache">Number of minutes to cache the file for</param>
/// <param name="debugMode">Output the debug information</param>
/// <returns>A control that can be inserted into a dasBlog template</returns>
public virtual Control GetRSS(
string xslVPath,
string rssPath,
int minutesToCache,
bool debugMode)
{...}

{
string cacheVDir =
"./content/getrsscache/";
string cachedFileLoc =
String.Empty;

StringBuilder output =
new StringBuilder();

bool writeToCache =
false;
bool cacheExpired =
false;
bool cacheExists =
false;
Debug output
#region Debug output
if (debugMode)
{...}

{

output.Append(
"<strong><start debug></strong><hr />\r\n");

output.AppendFormat(
"<i>RssPath</i>: {0}<br />\r\n", rssPath);

output.AppendFormat(
"<i>minutesToCache</i>: {0}<br />\r\n", minutesToCache);

output.AppendFormat(
"<i>CacheStorageFolder</i>: {0}<br />\r\n", cacheVDir);

output.Append(
"<hr />\r\n");

}
#endregion
Check whether we need to cache or not
#region Check whether we need to cache or not
if (minutesToCache >
0)
{...}

{

writeToCache =
true;
//Find the cache directory
string cacheDir =
HttpContext.Current.Server.MapPath(cacheVDir);
//Work out what the file would be called based on the RSS URL
cachedFileLoc = Path.Combine(cacheDir, HttpUtility.UrlEncode(TheSiteDoctor.GetMd5Sum(rssPath)) +
".cache");
Debug output
#region Debug output
if (debugMode)
{...}

{

output.AppendFormat(
"<i>cache file</i>: {0}\r\n", cachedFileLoc);

}
#endregion
if (!File.Exists(cachedFileLoc))
{...}

{

cacheExpired =
true;
Debug output
#region Debug output
if (debugMode)
{...}

{

output.Append(
"<i>cache age</i>: no file exists<br />");

}
#endregion
}
else
{...}

{

FileInfo info1 =
new FileInfo(cachedFileLoc);

TimeSpan span1 = (TimeSpan)(DateTime.Now - info1.LastWriteTime);
if (span1.TotalMinutes > minutesToCache)
{...}

{

cacheExists =
true;

cacheExpired =
true;

}
Debug output
#region Debug output
if (debugMode)
{...}

{

output.AppendFormat(
"<i>cache age</i>: : {0} min old <br />\r\n", span1.TotalMinutes);

}
#endregion
}

}
else
{...}

{
Debug output
#region Debug output
if (debugMode)
{...}

{

output.Append(
"<strong>caching disabled - CacheStorageAgeLimit=0</strong><br /><span style=\"color:red; font-weight: bold;\">FYI: All requests to this page will cause a new server request to the RssPath</span><br />");

}
#endregion
cacheExpired =
true;

}

#endregion
Debug output
#region Debug output
if (debugMode)
{...}

{

output.Append(
"<hr />");

}
#endregion
//Check whether or not the cache has expired
if (cacheExpired)
{...}

{
Debug output
#region Debug output
if (cacheExists & debugMode)
{...}

{

output.Append(
"<strong>file cache is expired, getting a new copy right now</strong><br />");

}
else if (debugMode)
{...}

{

output.Append(
"<strong>no cache, getting file</strong><br />");

}
#endregion
//The cache has expired so retrieve a new copy
output.Append(TheSiteDoctor.delegateRss(xslVPath, rssPath,
0, writeToCache, cachedFileLoc, debugMode));

}
else
{...}

{
Debug output
#region Debug output
if (debugMode)
{...}

{

output.Append(
"<strong>cool, we got the file from cache</strong><br />");

}
#endregion
//The cache still exists and is valid
StreamReader reader1 = File.OpenText(cachedFileLoc);

output.Append(reader1.ReadToEnd());

reader1.Close();

}
Debug output
#region Debug output
if (debugMode)
{...}

{

output.Append(
"<hr /><strong><end debug></strong>");

}
#endregion

output.Append(
"\r\n<!-- \r\ndasBlog RSS feed produced using the macro from Tim Gaunt\r\nhttp://blogs.thesitedoctor.co.uk/tim/\r\n-->");

return new LiteralControl(output.ToString());

}

/// <summary>
/// RSS feed retrieval worker method. Retrieves the RSS feed
/// and applies the specified XSL document to it before caching
/// a copy to the disk -this should be called after it has been
/// established the cache is out of date.
/// </summary>
/// <param name="xslVPath">The virtual path of the XSL file</param>
/// <param name="rssPath">The RSS feed URL</param>
/// <param name="timeoutSeconds">Number of seconds before the request should timeout</param>
/// <param name="writeCache">Whether to cache a copy on disk</param>
/// <param name="xmlPath">Physical path of the XML file on the disk</param>
/// <param name="debugMode">Output the debug information</param>
/// <returns>An XML document as a string</returns>
private static string delegateRss(
string xslVPath,
string rssPath,
int timeoutSeconds,
bool writeCache,
string xmlPath,
bool debugMode)
{...}

{

StringBuilder output =
new StringBuilder();
bool errorThrown =
false;
string cacheVDir =
"./content/getrsscache/";
string xslPath =
HttpContext.Current.Server.MapPath(xslVPath);

try
{...}

{
//TODO: Replace this with a HttpRequest and timeout to ensure the visitor is not left waiting for the file to load
//Load the XML
System.Xml.XmlDocument xmlDoc =
new System.Xml.XmlDocument();

xmlDoc.Load(rssPath);

//Load the XSL
System.Xml.Xsl.XslTransform xslDoc =
new System.Xml.Xsl.XslTransform();

xslDoc.Load(xslPath);

StringBuilder sb =
new StringBuilder();

StringWriter sw =
new StringWriter(sb);

//Apply the XSL to the XML document
xslDoc.Transform(xmlDoc,
null, sw);

//Append the resulting code to the output file
output.Append(sb.ToString());

}
catch (
Exception ex)
{...}

{

errorThrown =
true;
Debug output
#region Debug output
if (debugMode)
{...}

{
//Log the exception to the dasBlog exception handler
ErrorTrace.Trace(TraceLevel.Error, ex);

output.AppendFormat(
"<ul style=\"\"><li><strong>RSS request failed :(</strong> <br />{0}</li></ul>", ex.ToString());

}
#endregion
}

//Save a cache of the returned RSS feed if no errors occured
if (writeCache & !errorThrown)
{...}

{
//Find the cache's storage directory
DirectoryInfo dir =
new DirectoryInfo(
HttpContext.Current.Server.MapPath(cacheVDir));
//Check it exists
if (!dir.Exists)
{...}

{

dir.Create();
Debug output
#region Debug output
if (debugMode)
{...}

{

output.AppendFormat(
"<strong>just created the directory:</strong> {0}<br />",
HttpContext.Current.Server.MapPath(cacheVDir));

}
#endregion
}
//Create the file
StreamWriter writer1 = File.CreateText(xmlPath);

writer1.Write(output);

writer1.Flush();

writer1.Close();
Debug output
#region Debug output
if (debugMode)
{...}

{

output.Append(
"<strong>just wrote the new cache file</strong><br />");

}
#endregion
}

return output.ToString();

}

/// <summary>
/// Worker method to identify the MD5 checksum of a string
/// in this instance used to ensure the RSS file isn't already
/// cached (based on the URL supplied)
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string GetMd5Sum(
string str)
{...}

{

Encoder encoder1 = Encoding.Unicode.GetEncoder();
byte[] buffer1 =
new byte[str.Length *
2];

encoder