views:

102

answers:

5

I'm getting the chance to develop a mildly complex project and have been investigating the various approaches that I can use to tackle this project. Typically I would have ran with the traditional 3-Tier approach but after spending some time looking around at various options I've got an inkling that some kind of ORM might be a better fit and I'm considering nHibernate. However, I'm looking for some guidance on implementing nHibernate and more specifically how I would structure my BL and DAL in conjunction with nHibernate.

With nHibernate I would create my Objects (or DTOs?) and use nHibernate methods for my CRUD interactions all in my DAL. But what I can't get my head around is the Objects defined in the DAL would be probably be better situated within the BL, i.e. where validation and other stuff can be performed easily, and I just use the DAL from the various ObjectFactory's / ObjectRepositories. Unfortunately it seems through the many articles I've read this isn't mentioned or skirted over and I'm a tad confused.

What is the more accepted or easier method of implementation when using nHibernate in a 3 Tier system? Alternatively, what is the conventional method of exposing objects through the business layer from the data layer to the presentation?

+1  A: 

My personal experience with nHibernate has led me to decide that the data access layer becomes so thin it never has made any sense to me to separate it from the business logic. Much of your data access code is already separated into xml files (or various other distinctive methods like Fluent nHibernate) and since joins are handled almost transparently your queries using criteria objects are rarely more than a few lines.

Spencer Ruport
This is kinda how I'm thinking things might pan out, at the moment my thinking is something like this...
SeanCocteau
I create my POCO's representing my Business Objects within the Business Layer, e.g. Customer, Order, etc. as well as adding my Hibernate mappings. I then utilise the IRespository pattern creating a respository for each appropriate object, e.g. CustomerRespository, OrderRespository, etc. that abtracts any nHibernate guff allowing WCF to easily pass the object? Within my Data Layer I include the appropriate Hibernate Session management (through a Singleton?) and AbstractRepository class that deals with nHibernate methods in the actual data layer.
SeanCocteau
This is the conclusion I'm coming (rapidly) to and that benefit of the abstract of the DAL still remains, the BL will house the Business Objects, Mapping Files and associated Repostories
SeanCocteau
+1  A: 

I suspect you're overthinking this. nHibernate is basically a pretty simple tool; what it basically does is manage the serialization of your records in your database to and from similarly structured objects in your data model. That's basically it. Nothing says you can't encapsulate your Hibernate objects in Business Layer objects for validation; that's perfectly fine. But understand that the operations of validation and serialization are fundamentally different; Hibernate manages the serialization component, and does it quite nicely. You can consider the Hibernate-serializable objects as effectively "atomic".

Basically, what you want is this: nHibernate IS your Data Access Layer. (You can, of course, have other methods of Data Access in your Data Access Layer, but if you're going to use Hibernate, you should keep to the basic Hibernate data design, i.e. simple objects that perform a relatively straightforward mapping of record to object.) If your design requires that you use a different design (deeply composited objects dependent upon multiple overlapping tables) that doesn't map well into Hibernate, you might have to abandon using Hibernate; otherwise, just go with a simple POCO approach as implied by nHibernate.

McWafflestix
-1 wish i could -10 for the statement "nHibernate is basically a pretty simple tool" this is completely inaccurate. The session management of NHibernate is one of the most inordinately complex relationships I had to ever deal with in software development.
Chris Marisic
and another -1 for stating that you should abandon Nhibernate when your design requires deeply composited objects.. Nhibernate makes this a breeze compared to many other tools i have tryed
Noctris
@Noctris I would actually have to agree on that point for the keyword Deeply, with NHibernate you rarely ever want to go more than 2-3 nestings deep in objects because after that your sql query could end up with dozens of joins. This is very easily seen once you start doing inheritence where a Contact inherits from Person and an Employee inherits from a Contact, the Person object has a collection of address and phones. At this point you have 5 or 7 tables depending whether you model the collections as many-to-many or not.
Chris Marisic
@Noctris: don't be a douche. The statement was "IF your design requires that you use a different design that doesn't map well into Hibnerate, you MIGHT have to abandon using Hibernate"; I didn't "state that the OP should abandon Hibernate". Two qualifiers; IF and MIGHT is not "stating that you should abandon Hibernate".
McWafflestix
@ChrisMarisic: I wasn't trying to oversimplify nHibernate; I agree that session management can be extremely difficult. That's why I said it's "basically" a pretty simple tool; like ANY effective tool, there are deep layers of complexity that can make it very hard to work with. With the OP's original statement, though, that they're starting basically from scratch, that allows them to design around the session management issues of nHibernate, which reduces the effective complexity.
McWafflestix
That would be similar to stating well driving a car is basically pretty simple, you push the gas pedal and go. It works great until you find that brick wall infront of you.
Chris Marisic
@ChrisMarisic: I don't disagree with your point about complexity; it's just that things are different when you're able to design around the fundamental problems. To extend your analogy; if the task is "driving" and the problem is "running into brick walls", then you can design a process by which your car is on rails, for example. (Which presumably don't have brick walls on them.) So long as your destinations are fixed, it's an okay solution around the problem.
McWafflestix
I think you two are reading into this post too much. I read those statements completely differently than both of you. 1) A tool can be simple and still require a lot of skill to master. 2) nHibernate may not be suitable for all types of applications.
Spencer Ruport
@SpencerRuport: Exactly.
McWafflestix
A: 

I have NHibernate based apps in production and while it's better than most DALs, I'm at the point I could never recommend anyone use NHibernate any longer. The sophistication that is required to work with the session to do any advanced application is just absurd. For doing simple apps NHibernate is very trivial for enterprise application the complexity is off the charts.

At this point I've went to the decision to solve data access with 3 different choices depending on scope, using a document database (specifically Raven currently) for full scale application, for medium amounts of data access using LinqToSql and for trivial access I'm actually using raw ADO.NET connections with great success.

For reference, these statements are after I've spent 2+ years of development time using NHibernate and every time I've ever felt like I understood NHibernate fully I would run into some new limitation or giant monkey wrench I have to do deal with. It's also lead me to realize I started designing applications in regards to NHibernate which is one of my number one biggest reasons for using an ORM to not have my applications' design be dictated to by the database.

Not having to deal with session management with the complexity of NHibernate has been one of the largest boons to me for moving to RavenDB. With Raven you have very little need to manage the session except when you're doing extreme performance optimization or working with batch actions.

Chris Marisic
I'm not sure what kind of sophistication you're talking about when it comes to the session. At least for web applications I've found that the HybridSessionBuilder that you can see people using around the web on various nHibernate blogs makes session management fairly painless. http://jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple/
Spencer Ruport
Try implementing the long conservation pattern with NHibernate in a web enviroment, after 2 years I've given up and accepted it's just not fundamentally possible with NHibernate.
Chris Marisic
This guy seems to think he did: http://dotnetchris.wordpress.com/2009/12/18/implementing-nhibernate-long-conversation-with-no-httpmodules-or-aop-build-time-weaving/
Spencer Ruport
@Spencer thanks for reminding me to put a giant warning sticker on my post there.
Chris Marisic
+1  A: 

I'm a fan of letting the architecture emerge, but this is what my starting architecture would look like on typical ntier asp.net mvc project if I were starting it today using NHibernate.

First off, I would try to keep as much domain code out of the controller as possible. Therefore, I would create a service layer / facade over the business layer that the controller (or code behind) makes calls to. I would split my objects into two types: 1) objects with business behavior that are used on the write side, and 2) ViewModel / DTO objects that are used for displaying data and taking the initial data entry. These DTO's would have all of the view specific concerns like simple validation attributes etc... The DTOs could have their own NHibernate mappings, or they could be projected using NHibernate's AliasToBean feature. They would be mapped to business objects once they get passed the controller in operations.

As far as the Data Access layer goes, I would probably would use NHibernate directly in the service layer. I would not use the repository pattern unless I knew that I had to be able to swap out the ORM. NHibernate is already a persistence abstraction. Putting a repository over it makes you give up a lot of features.

Daniel Auger
"Putting a repository over it makes you give up a lot of features." I would disagree with this devoutly, implementing the repository pattern on top of it is a great way to get access to the goodness of NHibernate trivially. I have a blog on this part which is the best thing I've ever achieved with NHibernate. http://dotnetchris.wordpress.com/2010/03/15/creating-a-common-generic-and-extensible-nhiberate-repository-version-2/
Chris Marisic
When I said repository pattern, I was thinking more along the lines of a ORM agnostic one. I see yours is NHibernate specific, therefore you are not giving up any features. I would use something like that or, more likely, the query object pattern (which is basically a bunch of ultra specific repos).
Daniel Auger
A: 

My 02 cents ( since there is no on-answer-fits-all):

The DAL should ONLY be responsible for data retrievel and persistence.

you can have a library containing your Model ( objects) which are filled by the DAL, but are loosly coupled (in theory, you should be able to write a new DAL using other technology and plug it instead of the NHIBERNATE one, even if you are not going to)

for client<-> BL talk, i would seriously advice views/dto's to avoid model coupling with the client (trust, me.. i'm cleaning up an application like this and it's hell)

anyways.. i'm talking about the situation we are using here which follows this structure:

client (winforms and web) <-> View/Presenter <-> WCF Services using messages <-> BL <-> DAL

Noctris