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 bus
The ISession is very inexpensive to open/close. The problem with keeping it open for too long is that the connection pool can't reuse the connection until it times out or what not. This could be a problem in a multiuser application.
In your scenario I'd probably go for a service oriented approach to store retrieve data. meaning the DTO would only be used internally within the service boundaries. If you need to copy objects that look the same I suggest you have a look at AutoMapper which was created for this specific purpose. If you have a windows only or web only project then it's not a problem. It's when you mix. You can't handle the sessions the same way in a Windows app as in a Web app.
DTO's are meant to be "data transfer objects". That is, dumb objects used for passing values or collections of values around in your system. They shouldn't be responsible for persisting themselves, or even map 1-1 to domain objects in your domain layer.
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>()