Toph - Early Architecture Decisions

by November 9, 2012 12:29 PM

In Another Gig Completes, I mentioned planning to start a new project to help track consulting gigs. Here I introduce you to:

Toph

Project codename named after Toph from the Avatar: The Last Airbender

As I mentioned before, this project is meant not only to help organize my consulting gigs, but also give me a public project and codebase I can point to. I also hope to use the project as blogging fodder. Speaking of which...

Early Architecture Decisions

I've spent the vast majority of my career joining existing projects. There is always that sense of "that's not the way I would have done it". Well, I finally get to do it my way! It was tempting to go crazy with it and implement everything cool I've been reading about recently - whether needed or not, I might add. In the end I decided to go with a pragmatic approach that is much more likely to be a useful example I can point to when talking to developers as I continue consulting.

Visual Studio Projects

I'm still a fan of and will continue to advocate onion architecture (some might say Hexagonal Architecture). One difference you'll find between Toph and what I normally do though, is the lack of an Infrastructure project.

There seems to be a theme going around the blogosphere that is advocating the removal of unnecessary abstractions and part of the theme has been the combining of projects. The idea is that it is perfectly possible to create an architecturally sound solution without using Visual Studio projects to enforce it. In case you're wondering how they "enforce" it, realize that Visual Studio projects won't allow circular references between two projects - whether by directly referencing each other, or indirectly (A - B - C - A would not compile). Therefore if you have a UI and a Core project with UI referencing Core, you couldn't reference UI from Core.  Thus, this usually prevents you from directly doing UI type actions from within Core since you couldn't touch the controllers or view models.

I'm almost always a fan of pragmatic programming. As it turns out, the Infrastructure project never proved that exciting for me as a standalone project. So I just created a namespace within UI called Infrastructure and dumped everything in there. You see, everything usually consider Infrastructure is generally only used during application startup anyway as I'm building up the inversion of control container.

However, I still very much like having my Core separate. It just feels right. So, I decide three projects are all we'll need in this solution

  • Toph (I decided there was no reason to call it Toph.Core)
  • Toph.UI
  • Toph.Tests

Even if I end up adding another project in the future for scheduled tasks (to be run on some application server somewhere), leaving Infrastructure under UI should still be fine. That's because I generally just invoke endpoints in the UI from those background tasks rather than directly dealing with the domain or application's database.

UI

New projects should always be started with the latest and greatest, right? I went with ASP.NET MVC 4 of course. Specifically, I started with the Internet Application project template.

Data Access

That template starts with using a local database and using Entity Framework as its ORM of choice. As expected if you know me, I changed that use SQL Server 2012 Express and NHibernate. To do that...

  1. Delete InitializeSimpleMembershipAttribute. This is the attribute added to AccountController that ensures the database exists and is initialized. There is only one line in there that is needed: WebSecurity.InitializeDatabaseConnection.  I moved that into Application_Start
  2. Delete UsersContext. This is the EF DbContext
  3. Move UserProfile from the Models directory into the domain and kill the EF attributes
  4. Add Fluent NHibernate
  5. Do all the normal NHibernate config and mapping stuff
  6. Change your connection string
  7. Create the database with the single UserProfile table
  8. Run the application

That should do the trick.

Other notables

The only other things I added to the project were Structuremap and my personal code library RobTennyson.Common.

I also stuck with restricting domain access to a Service Layer like I usually do. One difference I thought I'd toss into the mix this time is a bit of CQS goodness (not full blown CQRS, mind you). We'll see how this turns out as the project grows.

Grabbing a copy and playing

If you're interested in playing around with this, but sure you get the code specifically from this commit: 91a19e9f8b

I'll be moving on with the project of course, but at that exact point, the project is still basically just the default template - well, juiced up a bit, but basically still has nothing to do with the real project in it yet.

Happy coding

Tags: , , , ,

Getting Started with NHibernate

by October 14, 2009 11:40 PM

I gave a presentation to our internal user group at work today (devloop). The topic of the day was "Getting Started with NHibernate". I'd say it went alright.. there was plenty of interest and several people wanted the code afterward. Good sign I suppose. However, I thought I did a crappy job.

  • I didn't prepare hardly at all (though I was given very little notice)
  • I felt chaotic and rushed the whole time (common result of poor prep)
  • I did some things for the sake of time that I would never prescribe on a real project
  • I did some things that added too much noise to the topic at hand (MVC, repository, and unit of work for starters)

So then, I don't think I'll share today's mayhem that resembled C#. Instead I took some time this evening to put together my first screencast. This presentation goes way back to basics and focuses on nothing but getting going with nhibernate, linq to nhibernate, and fluent nhibernate. No patterns. No best practices. Just the absolute basics on getting going from scratch.

The code from the screencast: 2009-10-14_NHDemo.zip
The screencast: 2009-10-14_nhibernate.wmv (this seems to have gotten deleted!)

And finally, in case you're wondering...

All in all I had fun putting it together. I am quite sure there are more efficient ways of going about it though :)

Enjoy!

Tags: , , ,

Linq to NHibernate Repository

by August 31, 2009 09:50 AM

A colleague at work asked for some guidance on creating a generic repository that uses Linq to NHibernate and I thought I'd reply here instead of directly in case anyone else might find the information useful. First thing first, here is the repository I use on a project at work. I'll talk to interesting pieces of it below the code.

public interface IRepository
{
ISession NHSsession { get; }
/// <summary>
/// Loads a proxy object with nothing but the primary key set.  
/// Other properties will be pulled from the DB the first time they are accessed.
/// Generally only use when you know you will NOT be wanting the other properties though.
/// </summary>
T Load<T>(object primaryKey);
T Get<T>(object primaryKey);
T Get<T>(Expression<Func<T, bool>> predicate);
IQueryable<T> Find<T>();
IQueryable<T> Find<T>(Expression<Func<T, bool>> predicate);
T Add<T>(T entity);
T Remove<T>(T entity);
}
public class Repository : IRepository
{
static Repository()
{
_sessionFactory = Fluently.Configure()
.Database(OracleDataClientConfiguration
.Oracle9
.ConnectionString(c => c.FromConnectionStringWithKey("CPSDsn"))
.Driver("NHibernate.Driver.OracleClientDriver")
.ShowSql()
)
.Mappings(mapping => mapping.FluentMappings.AddFromAssemblyOf<Repository>())
.ExposeConfiguration(config => config.SetInterceptor(new AppInterceptor()))
.BuildSessionFactory();
}
private static readonly ISessionFactory _sessionFactory;
private static ISession _testingSession;
public static ISession NHSession
{
get { return HttpContext.Current == null ? _testingSession : HttpContext.Current.Items["_nhSession"] as ISession; }
set
{
if (HttpContext.Current == null)
_testingSession = value;
else
HttpContext.Current.Items["_nhSession"] = value;
}
}
public static void BeginUnitOfWork()
{
if (NHSession != null)
throw new ApplicationException("Unit of Work already started");
NHSession = _sessionFactory.OpenSession();
NHSession.FlushMode = FlushMode.Commit;
NHSession.BeginTransaction();
}
public static void EndUnitOfWork()
{
if (NHSession == null) return;
NHSession.Transaction.Rollback();
NHSession.Dispose();
NHSession = null;
}
public static void SubmitChanges()
{
try
{
NHSession.Transaction.Commit();
NHSession.BeginTransaction();
}
catch
{
NHSession.Transaction.Rollback();
throw;
}
}
public static void CloseSessionFactory()
{
_sessionFactory.Dispose();
}
/*******************************************************************************/
/*******************************************************************************/
public Repository()
{
_session = NHSession;
}
private readonly ISession _session;
public ISession NHSsession { get { return _session; } }
public T Load<T>(object primaryKey)
{
return _session.Load<T>(primaryKey);
}
public T Get<T>(object primaryKey)
{
return _session.Get<T>(primaryKey);
}
public T Get<T>(Expression<Func<T, bool>> predicate)
{
return Find<T>().SingleOrDefault(predicate);
}
public IQueryable<T> Find<T>()
{
return _session.Linq<T>();
}
public IQueryable<T> Find<T>(Expression<Func<T, bool>> predicate)
{
return Find<T>().Where(predicate);
}
public T Add<T>(T entity)
{
_session.Save(entity);
return entity;
}
public T Remove<T>(T entity)
{
_session.Delete(entity);
return entity;
}
}

If I were looking at this for the first time, I think these things would jump out at me:

  • Static constructor - we're not using an IoC container to manage the NH session or session factory, so I saw this as the best way to reliably initialize the session factory. Remember that static constructors are guaranteed to be thread safe and are only called once. Pretty much exactly what we need for the NH session factory.
  • All the other static members - since we're not managing the NH session with IoC either, I needed a way to get a session. Also since this is from a web application I wanted the unit of work to be per http request. So in the Global.asax events BeginRequest and EndRequest, I call Repository.BeginUnitOfWork() and Repository.EndUnitOfWork(). And of course I didn't want any unexpected DB changes so you have to explicitly tell the repository to submit changes otherwise everything gets rolled back when ending the unit of work. The only thing remaining is the call to close the session factory. This is only used in unit tests.
  • All the NH specific stuff - yes, yes, I know. This isn't a repository you could plug into any ORM solution. I used to balk at such things that were implementation specific, but at some point I realized I was missing out on benefits of that chosen implementation. In fact, I'll talk to those benefits next.

Having talked to those things that JUMP out at you at first glance, the rest is pretty straight forward. The repository gives you what you need to get entities, get lists of entities, and of course add and remove entities from the DB.

The two methods that are specific to NH (I think) are the Load and Get methods (the Get that takes an object as primary key). Here are the reasons for their existence.

  • T Get<T>(object primaryKey) - if you use NHibernate's Get method, you'll get the added benefit of knowing NH might not have to go to the DB for that entity. If NH already has that entity loaded due to some previous call, then it will just return the one it already has. That's just freaking cool! If however, you use the other Get method that takes a predicate and uses the Linq method SingleOrDefault to get the entity, you'll hit the DB every time even if you're passing in the same predicate every time. Not cool.
  • T Load<T>(object primaryKey) - this one is very cool. If NH already has the requested object in memory, it will return to you the real deal. If not however, NH does not got to the DB to get it. Instead a proxy object is returned with nothing but the primary key set. You can use that object just as you would the real thing (pass it to constructors, use it as a parameter, etc). The intention is to use in situations where a reference to the entity is needed, but only for the sake of the relationship (FK in the DB usually), or to get to the primary key value. As a simple example, here is the body of one of the remove methods on one of my repositories: _repository.Remove(_repository.Load<MinorLine>(minorLineId));

I think that's about it. I hope you find it useful or that it at least sparks ideas for your own repository implementation.

Tags: , , ,

NHibernate Interceptors

by August 23, 2009 02:32 PM

A long time ago I asked a question on stackoverflow about table update events. The title of the question didn't really do it justice - I called it that because I assumed there would be events I could subscribe to in that would let me know when nhibernate was about to perform a database operation. In the end I figured out that what I was after is called an Interceptor.

The business case is simple: there is some data considered important enough we want to know everything that happens to the data. Classic auditing situation. The solution to these auditing needs however wasn't your standard single audit table. Instead, for any table containing "auditable" data, there is a sister table suffixed with "_HIST" that contains every column in the master table plus three additional - user, date, and action (Insert, Update, or Delete).

So when I joined the team and eventually introduced NHibernate, I started looking for a slick way to handle the auditing needs with NHibernate. My hope was that I could do something in the mappings and thus not have to change the domain entities themselves in any way. Unfortunately I never found something that would allow that, so the below is the best thing I could think of.

First, create an interface to implement on any entities who have auditing needs. This interface will not only tell the NHibernate code I show later that this is an entity to audit, but will also return the auditor that will do the work.

public interface IEntityToAudit
{
IAuditor Auditor { get; }
}
public interface IAuditor
{
void AuditInsert();
void AuditUpdate(object[] previousState, string[] propertyNames);
void AuditDelete();
}

The reason I'm passing in the previous state on update is because one of our entities only audits a few of the columns in the table it maps to. This means every time an update happens, I have to check those fields specifically to see if I need to insert a row in the audit table.

With that in place, all I have to do on my entities is implement the interface on any objects that map to a table we have to audit. For example:

public class MinorLine : IEntityToAudit
{
protected MinorLine()
{
Auditor = new MinorLineAuditor(this);
}
public MinorLine(string code, int costCenter) : this()
{
Code = code;
CostCenter = costCenter;
}
public virtual IAuditor Auditor { get; private set; }
public virtual int Id { get; protected set; }
public virtual string Code { get; protected set; }
public virtual int CostCenter { get; set; }
}

You might have noticed that we have to specify the actual implementation of the auditor here. This was for two reasons. First, I didn't want the NHibernate code to have to map from an object to all of the specific types that can be audited. Second, creating it here allowed me to pass in the entity under audit to the auditor's constructor, thus saving me from having to deal with the untyped data that I have in the NHibernate code.

The auditor itself unfortunately just does raw ADO.NET stuff.  When asked to do an AuditInsert, it inserts a new row into its audit table with an action of 'Insert'.  When asked to do an AuditUpdate, it does the same insert, but with an action of 'Update'. Each of my auditors have one method that does the actual insert. The three methods on the interface just delegate to that method passing in the action. So below, you can see _minorLine is the entity that was passed into the constructor and actionId is the method parameter specifying which action we're auditing.

cmd.CommandText =
"INSERT INTO MINOR_LINE_MASTER_HIST " +
"(                                  " +
"   MINOR_LINE_ID,                  " +
"   MINOR_LINE_CODE,                " +
"   COST_CENTER_NUM,                " +
"   ACTN_USERID,                    " +
"   ACTN_ID,                        " +
"   ACTN_DATE                       " +
")                                  " +
"VALUES                             " +
"(                                  " +
"   :MINOR_LINE_ID,                 " +
"   :MINOR_LINE_CODE,               " +
"   :COST_CENTER_NUM,               " +
"   :ACTN_USERID,                   " +
"   :ACTN_ID,                       " +
"   SYSTIMESTAMP                    " +
")                                  ";
DbHelper.AddInParameter(cmd, "MINOR_LINE_ID", _minorLine.Id);
DbHelper.AddInParameter(cmd, "MINOR_LINE_CODE", _minorLine.Code);
DbHelper.AddInParameter(cmd, "COST_CENTER_NUM", _minorLine.CostCenter);
DbHelper.AddInParameter(cmd, "ACTN_USERID", Username());
DbHelper.AddInParameter(cmd, "ACTN_ID", actionId);

At this point, I've shown you how I flag my entities as an entity to audit and how I handle the actual auditing. The only thing left is to wire up the code that calls the auditors at the right times. I'm using Fluent NHibernate for both the mappings and the configuration. In the configuration is where you tie together all this magic. Specifically, notice the call to "SetInterceptor"

_sessionFactory = Fluently.Configure()
.Database(OracleDataClientConfiguration
.Oracle9
.ConnectionString(c => c.FromConnectionStringWithKey("CPSDsn"))
.Driver("NHibernate.Driver.OracleClientDriver")
.ShowSql()
)
.Mappings(mapping => mapping.FluentMappings.AddFromAssemblyOf<Repository>())
.ExposeConfiguration(config => config.SetInterceptor(new AppInterceptor()))
.BuildSessionFactory();

And the AppInterceptor:

public class AppInterceptor : EmptyInterceptor
{
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
{
var entityToAudit = entity as IEntityToAudit;
if (entityToAudit != null)
entityToAudit.Auditor.AuditInsert();
return base.OnSave(entity, id, state, propertyNames, types);
}
public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, IType[] types)
{
var entityToAudit = entity as IEntityToAudit;
if (entityToAudit != null)
entityToAudit.Auditor.AuditUpdate(previousState, propertyNames);
return base.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
public override void OnDelete(object entity, object id, object[] state, string[] propertyNames, IType[] types)
{
var entityToAudit = entity as IEntityToAudit;
if (entityToAudit != null)
entityToAudit.Auditor.AuditDelete();
base.OnDelete(entity, id, state, propertyNames, types);
}
}

And that's it! Once in place, I've found that adding new entities to the domain with auditing needs is extremely easy. Just create the entity and do the mappings like you've always done. Then when you're ready, just implement the interface and the auditor and you're done.

Tags: ,