Adding Castle ActiveRecord to an MVC3 application

Install Castle ActiveRecord

In the NuGet package manager, install the Castle.ActiveRecord package.

PM> Install-Package Castle.Activerecord

Configure your application

Next, update your Web.config file to include the following settings:

<configuration>
  <configSections>
    <section name="activerecord" type="Castle.ActiveRecord.Framework.Config.ActiveRecordSectionHandler, Castle.ActiveRecord" />
  </configSections>

  <activerecord isWeb="true" isDebug="false" pluralizeTableNames="false">
    <config>
      <add key="dialect" value="NHibernate.Dialect.MsSql2008Dialect" />
      <add key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
      <add key="connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
      <add key="connection.connection_string_name" value="ApplicationServices" />
      <add key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle" />
      <add key="show_sql" value="false" />
    </config>
  </activerecord>

  <connectionStrings>
    <add name="ApplicationServices"
         connectionString="Data Source=.\SQLServer;Initial Catalog=[dbname];Integrated Security=True;" providerName="System.Data.SqlClient" />
  </connectionStrings>
  ...

Hook in the Initialization

Next, you’ll need to initialise ActiveRecord on application start. Update the Application_Start method in your Global.asax.cs file to include the first two lines in this sample:

protected void Application_Start()
{
    Castle.ActiveRecord.ActiveRecordStarter.Initialize();
    Castle.ActiveRecord.ActiveRecordStarter.UpdateSchema();

    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

The ‘UpdateSchema’ line is added as a development convenience, and should be taken out of a production system. It will update your database schema following changes to your models every time your application starts.

Automatically manage the session scope

Another convenience is to automatically manage your SessionScope. Create a base class for your controller that looks like this:

public class BaseController : Controller
{
    public Castle.ActiveRecord.SessionScope Scope { get; private set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!this.HttpContext.Items.Contains("ar.session"))
        {
            this.Scope = new Castle.ActiveRecord.SessionScope();
            this.HttpContext.Items.Add("ar.session", this.Scope);
            base.OnActionExecuting(filterContext);
        }
    }
}

The reason for putting it here, rather than in Application_BeginRequest, is that Application_BeginRequest gets called for every request to the web server, including static content. Creating the SessionScope object is a costly operation, and shouldn’t be performed unnecessarily. By putting it in the OnActionExecuting method of the controller, we only create the session when we need it. If you have controllers that don’t require database access, don’t inherit this base class.

We also need to dispose of the SessionScope, so add this method to your Global.asax.cs file:

protected void Application_EndRequest()
{
    if (HttpContext.Current.Items.Contains("ar.session"))
    {
        var session = HttpContext.Current.Items["ar.session"] as SessionScope;
        session.Dispose();
    }
}

This is placed here, rather than in the controller base class, because if lazy loading is enabled on your ActiveRecord models, the view will require the SessionScope, so disposing of it need to happen at the end of the Request, rather than the end of the action execution.

Start using it!

You’re now ready to create some models like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;

namespace Example
{
    [ActiveRecord]
    public class Foo : ActiveRecordLinqBase<Foo>
    {
        [PrimaryKey]
        public int ID { get; protected set; }

        [Property]
        public string Name { get; set; }
    }
}

In your controllers you can now query the model like this:

var foos = (from f in Foo.Queryable where name == "example" select f).ToArray();

Farewell SQL!


					
Advertisements