I’m learning NHibernate and have created some unit tests and it’s going quite well. My main app only has two layers:
- Presentation (WPF app)
- Domain (has business logic and data access)
and of course I have my Unit test project (Test).
My unit tests call my SessionManager class to build a SessionFactory during [TestFixtureSetup]. Each [Test] then gets a Session to perform the data access unit test. I’m wondering how I should do this in my WPF project.
I have created a simple dialog box to see if I can wire up my WPF app to my database. It feels wrong to have a reference to NHibernate in my Presentation layer, am I right in this feeling? If so, how should I get a session to store an object when a user clicks Add on my form to store something? Here’s some of my code:
public class SessionManager
{
private ISessionFactory _sessionFactory;
public SessionManager()
{
_sessionFactory = GetSessionFactory();
}
public ISession GetSession()
{
return _sessionFactory.OpenSession();
}
private ISessionFactory GetSessionFactory()
{
return (new Configuration()).Configure().BuildSessionFactory();
}
}
In my Test project I have this kind of thing:
[TestFixtureSetUp]
public void TestFixtureSetup()
{
log4net.Config.XmlConfigurator.Configure();
DatabaseFixtureSetUp();
_sessionManager = new SessionManager();
}
[SetUp]
public void Setup()
{
DatabaseSetUp();
_session = _sessionManager.GetSession();
}
I’m not sure how to structure my Presentation layer code to store an object. I have this on my form:
private void btnAddBroker_Click(object sender, RoutedEventArgs e)
{
var broker = new Broker
{
Name = txtBrokerName.Text,
IsActive = (bool)chkIsActive.IsChecked,
IsDefault = (bool)chkIsDefault.IsChecked
};
// save the broker object to the database
// is it ok to have NHibernate code here? feels wrong
}
How would you do it?
Although I’m not an expert in WPF applications, coming from Web Development, I would say yes It does feel wrong for the presentation layer to be generating a session.
My recommendation would be to create a Factory class (Which I see you did with SessionManager) that is responsible for creating a NHibernate Session. Your business layer could then call the factory class to get a NHibernate Session, then use it in your business layer to process whatever request that needs to be fulfilled.
You could then even inject that factory class and business layer using and Dependency Injection, if you are sticking to IOC principles.
I’m sure you already know this, but I’ll mention it anyway:
However you decide to split things up, the goal is to keep user interface manipulation code in one layer and business code in another, so that if you should need to port this application to, say a Web application, the business layer could be re-used and only the presentation layer would need to be developed.
Seeing that you are already doing unit testing, writing your unit tests first will force you naturally into thinking about splitting up responsibilities of classes in such a way that they are unit testable, and that is a very good thing. I believe you are on the right path.