Archive for July, 2009
Auto-Creating Your DB with Active Record
Jul 13th
During some recent development the team I was experiencing some friction with databases and developing. We were using Castle Active Record and we soon realized that as new people joined the team, left the team (rinse, wash, repeat), db changes occurred in the Active Record Schema etc, that the set up time to going was miserable.
The problem at the time is that you’d have to set up the DB in SQL Express (which is what we used during development), make sure the schema was correct, make sure you had the most recent baseline,change scripts, etc. We were not following a db change management workflow as in regards to version control as we were using Active Record (all schema is based off of the objects) and we were developing a new product from the ground up. Therefore once we were done we could auto-gen the scripts and go from there. At that point we could implement a version control process for our db.
To make a long story short … we wanted to be able to check in active record changes, and make updating the database as easy as visiting a route on the ASP.NET MVC Application. This route would update the database schema and update the tables, etc. The issue is that if the database was never created in the App_Data directory (we did not check in the .mdf into version control) then we would have a problem. We needed to create one on the fly.
How
Here’s how to create a database on the fly with a few simple SQL commands. Here is an example:
public void CreateDatabase(string filename)
{
string databaseName = System.IO.Path.GetFileNameWithoutExtension(filename);
using (var connection = new SqlConnection(
@"Data Source=.\SQLEXPRESS;Initial Catalog=tempdb;Integrated Security=true;User Instance=True;"))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText =
"CREATE DATABASE " + databaseName +
" ON PRIMARY (NAME=" + databaseName +
", FILENAME='" + filename + "')";
command.ExecuteNonQuery();
command.CommandText =
"EXEC sp_detach_db '" + databaseName + "', 'true'";
command.ExecuteNonQuery();
}
}
}
What we’re doing here is creating a database via file name and then disconnecting the database from the server. This leaves us with an mdf file sitting on the disk somewhere.
The ‘filename’ attribute specifies where the file (example.mdf) should go. This is obtained by executing the following code:
string dataDirectory = Convert.ToString(AppDomain.CurrentDomain.GetData("DataDirectory"));
string mdfPath = Path.Combine(dataDirectory, "admin.mdf");
After we create the database we need to create the schema’s. Here’s the call to do this:
public void CreateSchema(string path, string schema)
{
var connectionString =
String.Format(
@"Data Source=.\SQLEXPRESS;AttachDbFileName={0};Integrated Security=True;User Instance=True;", path);
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = String.Format("CREATE SCHEMA [{0}]", schema);
command.ExecuteNonQuery();
}
}
}
With the call above we have attached to the db using SQLExpress and created a schema through the CREATE SCHEMA call. We would call this method for each schema we had like this:
// Get your mdf path as shown above localDbManager.CreateSchema(mdfPath, "Customers"); localDbManager.CreateSchema(mdfPath, "Shipping"); localDbManager.CreateSchema(mdfPath, "Logistics"); // ... etc, etc, etc ...
Remember, this may look expensive in regards to setting up a db, but this is only called when the user requests it, OR, if set up to do so, such as at the time of initialization of the application (which is where I put this code – this allows the dev who is opening the app for the first time to get the latest and greatest in regards to the db set up when he/she starts the app).
Finally, we call:
ActiveRecordStarter.UpdateSchema();
This tells ActiveRecord To generate the scripts and run them against the current db.
At this point you would have a db up and running within your App_Data directory.
I have purposely left out a lot of details of how the app sets itself up, so I have included a sample app you can download and run. All of the assemblies are included. Download, open the sln, and run. As long as you have access to write a file to the file system, this will work.
Download Sample
The sample is a ASP.NET MVC application with the Spark View Engine. Other technologies used in the sample: Windsor Container, Castle Active Record
Important Notes: The Windsor.config file contains the ActiveRecord connection information. We use Windsor Container to inject and resolve instances in the controllers and other areas of the app. The app will attempt to create and update the db upon application start (global.asax) and you can force a schema update through the /admin/updateschema/ route.
![]()
Download Zipped Solution (5.3 MB)
Running the Sample
Running the sample is fairly straightforward. When the app starts you will be presented with this screen:
If you look in your App_Data directory you will see your admin.mdf file inside of the directory as such:
If you were to attach this to SQL Express Management Studio and looked at the DB, you would see the tables, etc.
To load data into the db for the sample, I have created a simple route that creates a random customer and loads it into the database. Click the link “Create Random Customer” and a random customer will be created. You can then click on the customer to view details about the customer or you can delete the customer by clicking on the “x”. Its a very rudimentary example, but it provides all of the end to end goop for you to grok this example.
Conclusion
By no means is this a replacement for your production DB. You’d never want to auto-gen your DB (unless it always started out empty, etc). This is the perfect scenario for an agile project where changes are made frequently and keeping db changes up to date across a developer team is a difficult task.
What about pre-loaded data for look up tables, etc?
This is a fairly simple problem to fix. I have created a property that is injected via setter injection into the Application.cs file. The property is “ShouldInitializeData”. If true (set this in the /config/WIndsor.config) the application will initialize some data with the DataInitializationService. Inside of this service you could call a handful of other services to initialize data, or you could perform the initialization inside of this service itself. Its up to you at this point. I have included this as part of the sample.
Enjoy.
ASP.NET MVC – Windsor Container Controller Factory
Jul 10th
Here is a simple class that allows you to use a container to register and resolve your instances of controllers. You’d want to do this if you inject dependencies into your controller via constructor injection.
Controller Example:
public class AdminController : Controller
{
private readonly ILocalDbManager _localDbManager;
public AdminController(ILocalDbManager localDbManager)
{
_localDbManager = localDbManager;
}
public ActionResult Index()
{
return View();
}
// Other Actions ...
}
If you use the default ControllerFactory provided by ASP.NET MVC you’ll get a MissingMethodException, such as this:
No parameterless constructor defined for this object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.
The default ASP.NET MVC Controller Factory looks for a parameter-less constructor to build the controller from. If it cannot find one, the above is what happens.
Since I want to use a container (Windsor in this case) to supply my depenencies, the default ControllerFactory will not work. We have to create our own.
The Container Controller Factory
Building your own controller factory is easy. Simply implement the IControllerFactory interface from the System.Web.Mvc namespace and then set your controller factory as the one to use. Here’s how to do it:
The Controller Factory
public class ControllerFactory : IControllerFactory
{
private readonly IKernel _kernel;
public ControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
public IController CreateController(RequestContext requestContext, string controllerName)
{
return _kernel.Resolve<IController>(controllerName.ToLowerInvariant() + "controller");
}
public void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
}
This class, takes a container in through the constructor, and then resolves a controller from the container via the name of the controller . It then releases it from the container when its done with it.
Please note, you can create your own naming structure when you register your controllers, and if you do so you’ll need to adjust the “CreateController” method to resolve to the proper key in the container.
Now that we have our own ControllerFactory, we need to put it INTO the container so we can have the kernel injected via the constructor.
This is a bit difficult to understand, therefore I’m going to post the code and then explain it.
Global.asax.cs
public class Global : System.Web.HttpApplication
{
public static WindsorContainer container;
protected void Application_Start(object sender, EventArgs e)
{
container = new WindsorContainer(Server.MapPath("~/Config/Windsor.config"));
var app = container.Resolve<Application>();
app.RegisterFacilities(container.Kernel);
app.RegisterComponents(container.Kernel);
app.RegisterRoutes(RouteTable.Routes);
app.RegisterViewEngines(ViewEngines.Engines);
// Tell MVC which controller factory to use. Since we're using
// the container to inject some items into the controller we need to use this controller factory
// that was set up in the component registration.
ControllerBuilder.Current.SetControllerFactory(container.Resolve<IControllerFactory>());
}
// Other global members below ...
}
Application.cs
public class Application
{
public void RegisterViewEngines(ViewEngineCollection engines)
{
if (engines == null) throw new ArgumentNullException("engines");
SparkEngineStarter.RegisterViewEngine(engines);
}
public void RegisterRoutes(RouteCollection routes)
{
if (routes == null) throw new ArgumentNullException("routes");
// default route
routes.Add(new Route(
"{controller}/{action}/{id}",
new RouteValueDictionary(new
{
controller = "home",
action = "index",
id = ""
}),
new MvcRouteHandler()));
}
public void RegisterComponents(IKernel kernel)
{
kernel.Register(
Component
.For<IControllerFactory>()
.ImplementedBy<ControllerFactory>(),
// Register all controllers in assembly.
AllTypes
.Of<IController>()
.FromAssembly(typeof (Application).Assembly)
.Configure(
reg =>
reg.Named(reg.Implementation.Name.ToLowerInvariant()).LifeStyle.Transient),
// Register all services that implement marker interface in current assembly
AllTypes.
Of<IService>()
.FromAssembly(typeof (Application).Assembly)
.WithService.FromInterface());
}
public void RegisterFacilities(IKernel kernel)
{
kernel.AddFacility("logging", new LoggingFacility(LoggerImplementation.Trace));
kernel.AddFacility("activerecord", new ActiveRecordFacility());
}
}
This is done in the Application.cs file (which is the bootstrapper for the container and other application details). This class is called on Application Start. We call a RegisterComponents on the Application.cs file and give it a container in which to register things.
In the RegisterComponents method call we register the ControllerFactory in the container, and then all of the other components. A key one to notice is this bit of code:
// Register all controllers in assembly.
AllTypes
.Of<IController>()
.FromAssembly(typeof (Application).Assembly)
.Configure(
reg =>
reg.Named(reg.Implementation.Name.ToLowerInvariant()).LifeStyle.Transient),
The code above analyzes the current assembly (which Application.cs resides within), and configures the container to load all instances of IController (which is implemented on the Controller base class in ASP.NET MVC). In short, it registers all controllers into the container. The dependency is registered with a key, that is the name of the controller. Therefore if you have a controller called “AdminController” the key would be “admincontroller”. We then set the life style to transient for each controller.
This naming structure has meaning. If we look at the ControllerFactory again below …
return _kernel.Resolve(controllerName.ToLowerInvariant() + "controller");
… we can see that when we resolve the controller from the container we use a string key and concatinate the “controller” to the end of it. This is the key in the container. At this point the proper controller will be returned. If you change yoru controller key structure you will need to change it in the registration as well as in the factory (as they depend on each other).
In the Global.asax.cs file we are setting up a new container, and upon Application Start we register the components, facilities, view engines, and a few other things (which the component registration is shown above). At the bottom of the Application_Start call, we tell the ControllerBuilder class (which is in the System.Web.Mvc namespace) to set the ControllerFactory to our own ControllerFactory … like this:
// Tell MVC which controller factory to use. Since we're using // the container to inject some items into the controller we need to use this controller factory // that was set up in the component registration. ControllerBuilder.Current.SetControllerFactory(container.Resolve<IControllerFactory>());
All Done
Now, when we fire up the app, the following will happen:
- The App Starts
- The Container is created
- The Container registers its components
- The controller factory gets registered, its dependency, IKernel, is injected from the kernel itself (it knows how to supply itself to an object if it needs it)
- The controllers get registered with key.
- Our new ControllerFactory is set to be the ControllerFactory to use when resolving controllers during runtime via the SetControllerFactory method.
- When a route is requested, our ControllerFactory will take over, the controller will be resolved via the key that is created by using the name of the current controller concatenated with the word “controller” (following a convention over configuration methodology).
- The controller is returned with all of its dependencies resolved, which in this case would be ILocalDbManager
- The app then continues to run.
At this point your able to create a controller which takes injected dependencies. This helps with decoupling, maintenance and also testing.
Unit Testing you Container Dependencies
Jul 10th
When developing with an inversion of control container (I use Windsor) its sometimes difficult to detect if your instances in your container are creatable or not. A lot of times this is determined when you run the app, you’ll get an exception informing you that your object does not have all of its dependencies fulfilled.
Therefore…the real question is …
Did you register everything in the container? Or did you forget something?
I know from personal experience I’ve forgotten to register components many times so I started relying on unit tests to catch me when I failed.
How to Test that you Registrations are Creatable
This simple unit test will assert that your components are creatable.
[Test]
public void All_components_in_container_should_be_creatable()
{
var kernel = new DefaultKernel();
var handlers = new List<IHandler>();
kernel.ComponentRegistered += (name, handler) => handlers.Add(handler);
// Used in our Global.asax on App Start to register our components.
var app = new Application();
// Same call that we make in Global asax
app.RegisterComponents(kernel);
// If the container (kernel) cannot resolve the instance
// an exception will be thrown and the test will fail
handlers.ForEach(handler =>
{
if (handler.CurrentState == HandlerState.WaitingDependency)
kernel.Resolve(handler.ComponentModel.Name, handler.Service);
});
}
Code Explained
Background: In all of the apps I write now I have an Application.cs file. This file is responsible for bootstrapping the container and everything else the app needs to run (Logging, Diagnostics, Facilities, etc). Inside of this Application.cs file I have a “RegisterComponents” call which registers all of the required components in the container.
Therefore, the code above creates a new container (kernel) and then we create a list of IHandler’s. An IHandler is an interface in Windsor Container (the container I’m using here) that manages component state and coordinates its creation and destruction.
The next line is a sweet little lambda expression that says …
“When a component is registered in the container, I want to add its handler to a list of Handlers”
Which of course, is the list we just created.
The next few lines set up the application and register the components.
The last call in the test is where the magic happens.
We iterate over the list of handlers and check their CurrentState property. If the state of the component is still waiting for a dependency to be resolved (perhaps it has something injected into the constructor) we will then try to resolve the component with the name of the component and service type. If it can be resolved, it will resolve and nothing will happen (which is good). However… if the container _cannot_ resolve the component, an exception of type Castle.MicroKernel.Handler.HandlerException will be thrown.
The exception looks like this:
Castle.MicroKernel.Handlers.HandlerException: Can’t create component ‘Foo.Bar.OrderRepository’ as it has dependencies to be satisfied.
‘Foo.Bar.OrderRepository is waiting for the following dependencies:
Keys (components with specific keys)- dataStore which was not registered.
- dataMapper which was not registered.
As we can see above, the “Foo.Bar.OrderRepository” could not be resolved as the container could not find the “dataStore” parameter, or the “dataMapper” attribute.
At this point your test will fail and you’ll see that you have an issue with your container set up. Investigate, fix and retest!
A True Life Git Story …
Jul 7th
Recently I took a trip to South Carolina (which was a ton of fun). We ended up in a place which isn’t known for its high speed internet … and a WIFI signal could not be identified for nearly nearly 15 miles (I know because I had a WIFI detector enabled on my G1 when we drove around). I needed to do some development over the week, but this development was a major change to some software I was writing. I needed the ability to branch, merge, check-in, revert, etc _without_ being connected to the internet, because I knew it would be over a week before I’d re-connect. Without this ability I’d have to create manual copies of my files, perform manual diffs of the files and manually merge/revert … aka: shoot myself in the foot.
Luckily, I had GIT installed. If you don’t know what it is, click on the link on the left. GIT enabled me to create a repository of my current work, (I was working with SVN previously for the project) branch for a new large feature and make frequent check-in’s throughout my development. I was able to create two new versions of my product on separate branches, all while maintaining a version history with full revert capability (which I ended up using a few times).
Once I was connected back at home, I was able to submit a pull request up to a GitHub.com private repository and pull the branched changes up (that’s not all of the steps I did, but this is what the end result pretty much came down to).
From here on out, I’m pretty much sold on the features that GIT comes with OOB as it provided the ability to work remotely, completely disconnected with a full VCS at my fingertips (which I used extensively).
Mark me down as another GIT convert.