I'm new to NHibernate (and ORMS) and trying to come to grips with the myriad of different options it presents. For reference, I'm using Fluent NHibernate with seperate business objects which in turn use DTO's purely for data access. My application architecture must support both windows and web "front ends".
My quandry is one of general approach as there seem to be so many options. My DTO's look something like the sample below. Each DTO has a reference to an ISession which is passed to them from the BO. They are responsible for their own load and save:
public class EmployeeDTO...
// Data Properties to be persisted to the database
public virtual int Id { get; private set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual ISession Session { get; set; }
// Save logic
public virtual void Save()
{
var transaction = Session.BeginTransaction();
Session.SaveOrUpdate(this);
transaction.Commit();
}
// Load logic
public virtual void Load(int id)...
First of all: Is this the correct approach to take - should the DTO have the ability to save and load itself?
Secondly: Regardless of where the save/load code lies, should you use the same ISession for the lifetime or an object, or should they have a ref to the ISessionFactory and open a new session every time database interaction is required?
// Open a new session every time I interact with the repository
var session = FluentSupport.SessionFactory.OpenSession();
var transaction = Session.BeginTransaction();
Session.SaveOrUpdate(this);
transaction.Commit();
session.Close();
// Close the session when I'm done
Of course there's always option 3, none of the above :)
In general, DTOs do not contain behavior (like Save, Load) and do not contain knowledge of how they get persisted (ISession). It sounds like what you are really creating is a data layer. Your business layer ideally shouldn't know about ISession either. That said, you can shortcut this layering all you want as it fits your needs, but it will likely be difficult to change to a different ORM later if your ORM bleeds through all your layers.
For ISession lifetime management, you have to decide if you are going to use the UnitOfWork pattern, which basically says every user request gets a new ISession. There are other options for ISession lifetime as well and you really aren't limited in that regard. Often, there may be best practices around web apps vs. windows apps vs. whatever other application types, but you didn't specify which you were writing.
Keep your loading/saving code separate from your DTOs. The DTO objects are only views of the underlying data.
When doing your queries, return the DTOs by using a transformation. Something like this:
resultSet = session.CreateCriteria(typeof(MyDataObject))
.Add(query criteria, etc.)
.SetResultTransformer(Transformers.AliasToBean<MyDTOObject>())
.List<IMyDTOObject>()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With