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.

Sunday, April 25, 2010

Testing MVC Routes in C# and Moq

To enable you to test the custom routes that you have set-up firstly create a new RouteManager class.
public static class RouteManager
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"CustomParameter",
"ControllerName/{action}/{Param1}/{Param2}",
new { controller = "ControllerName", action = "ActionName", Param1 = "", Param2 = "" }
);

routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);

}
}

You can then refactor your Global.asax.cs file to use the RouteManager:
protected void Application_Start()
{
RouteManager.RegisterRoutes(RouteTable.Routes);
}

With this set-up it is easy to test your MVC routes. The following code is an example of a simple routing test: ~

private static RouteData GetRouteData(string context)
{
var routes = new RouteCollection();
var mockOfHttpContext = new Mock();
mockOfHttpContext.Setup(httpContext => httpContext.Request.AppRelativeCurrentExecutionFilePath)
.Returns(context);
RouteManager.RegisterRoutes(routes);
return routes.GetRouteData(mockOfHttpContext.Object);
}

private static RouteData CheckMapping(String controller, String action, String suffix)
{
var context = "~/" + controller + "/" + action + "/" + suffix;
var routeData = GetRouteData(context);
Assert.AreEqual(controller, routeData.Values["controller"]);
Assert.AreEqual(action, routeData.Values["action"]);
return routeData;
}

[TestMethod]
public void MapsToDefaultRoute()
{
var expectedValue = "ParameterValue";
var routeData = CheckMapping("Controller", "ActionName", expectedValue);
Assert.AreEqual(expectedValue, routeData.Values["id"]);
}

[TestMethod]
public void MapsToCustomRoute()
{
var expectedValueForParam1 = "ParameterValue";
var expectedValueForParam2 = "ParameterValue";
var routeParameters = expectedValueForParam1 + "/" + expectedValueForParam2
var routeData = CheckMapping("ControllerName", "ActionName", routeParameters);
Assert.AreEqual(expectedValueForParam1, routeData.Values["Param1"]);
Assert.AreEqual(expectedValueForParam2, routeData.Values["Param2"]);
}

Mocking an MVC Controller in C# and Moq

When unit testing an MVC controller you will on occasions be required to mock out the controller context. The following code is the basis to allowing this.

namespace ProjectNamespace
{
public class FakeControllerContext
{
public ControllerContext ControllerContext { get; private set; }

private readonly Mock<ControllerBase> _mockOfControllerBase;
private readonly Mock<HttpContextBase> _mockOfHttpContextBase;
private readonly Mock<HttpSessionStateBase> _mockOfHttpSessionStateBase;

public FakeControllerContext()
{
_mockOfControllerBase = new Mock<ControllerBase>();
_mockOfHttpContextBase = new Mock<HttpContextBase>();
_mockOfHttpSessionStateBase = new Mock<HttpSessionStateBase>();

ControllerContext = new ControllerContext(_mockOfHttpContextBase.Object, new RouteData(), _mockOfControllerBase.Object);
}
}
}


Once this class has been set-up then you can set the context of your controller as follows: ~

var controller = new YourController() { ControllerContext = new FakeControllerContext().ControllerContext };