Saturday, July 30, 2011

Using NHibernate Projections.Max in a Subquery

I found myself in the need of doing a Subquery in NHibernate recently that would fetch the max value of a column as the data I was working with was versioned.

The SQL that I needed to replicate was essentially the follow:

SELECT * 
FROM databaseTable
WHERE property = 'value'
AND version = (SELECT MAX(version) FROM databaseTable WHERE property = 'value')


After a bit of investigation I found the following solution:

using(var session = _database.OpenSession())
{
var detachedCriteria = DetachedCriteria.For(typeof(DatabaseRecord))
.Add(Restrictions.Eq("Property", value))
.SetProjection(Projections.Max("Version"));

var record = session.CreateCriteria(typeof (DatabaseRecord))
.Add(Restrictions.Eq("Property", value))
.Add(Subqueries.PropertyEq("Version", detachedCriteria))
.UniqueResult<DatabaseRecord>();

if (record == null)
throw new Exception("No records were found where Property = " + value);

return record;
}

Friday, July 29, 2011

100% CPU Usage

I recently found myself trying to solve an issue that we had at work, whereby one of the load balanced servers would shoot up to 100% CPU usage, and then remain there until we recycled the application pool of the site that was causing the issue.

After some investigation a colleague of mine said, "Hold on, isn't this lock object supposed to static?" Sure enough we had a block of code similar the following:
public class SomeClass
{
private readonly IDictionary<string, string> _someList;
private readonly object _lockObject = new object();

public SomeClass()
{
_someList = new Dictionary<string, string>();
}

public string Get(string key)
{
string value;
if(!_someList.TryGetValue(key, out value))
{
lock (_lockObject)
{
if (!_someList.TryGetValue(key, out value))
{
value = GetValueFor(key);
_someList.Add(key, value);
}
}
}

return value;
}
}
We fixed the code by simply making '_lockObject' static as follows:
private static readonly object _lockObject = new object();
When we pushed this to live and all was fixed. It was a pretty obvious mistake but the symptoms were not immediately obvious to us as to what to look for so i thought I would put this out there on the tinterwebs for if anyone else encounters the same issue.