NHibernate with csla Again :(

NHibernate with csla Again :(

Old forum URL: forums.lhotka.net/forums/t/410.aspx


kariem2k posted on Monday, June 19, 2006

Hi

I fall in love with csla but also i want to use nhibernate for presistance.

So i am trying to inheret the CSLA BussinessBase<> class  to make the NHibernate class and mapping the public properties using the NHibernate attributes, But Unfortunately NHibernate uses proxies which need all of the class's properties and methods to be virtual but of course there are some non-virtual methods in BussinessBase and it's parent classes.

I have read that David Dilworth is using the same approach so i want how did he overcome this problem.

Thanks  

DavidDilworth replied on Monday, June 19, 2006

I'm not exactly sure what you mean when you say "need all of the classes properties and methods to be virtual".

We are able to persist our BOs exactly as you would expect by just attributing the properties we want to include in the NHibernate mapping.

Neither did we do anything to make NHibernate use proxies.  We're just using plain NHibernate with no special tricks.

Have you read through all the NHibernate and Hibernate documentation?

Perhaps you could post an example of what you are trying to do?

came replied on Monday, June 19, 2006

I'm also interessted in David's way of combining csla and nhibernate. However, reading his posts and knowing a bit of nhibernate I got the impression, that using nhibernate to persist the csla BOs I start building my BOs around the data and not around the business functionality. Maybe I'm wrong, but one nice thing about csla I thought would be to have the opportunity to get my business data from wherever I want to and even from multiple sources. And, am I not bound to one db table once I start using nhibernate to persist my BO? 
...just tell me I'm wrong, what's my error of reasoning.
Thanks a lot...

DavidDilworth replied on Monday, June 19, 2006

You're wrong  Wink [;)]

Yes, you should work exactly the way you want to, in an OO style.

NHibernate just gives you a way of doing the ORM bit. 

You can persist BOs across multiple tables and get BOs from different data sources if you want.

kariem2k replied on Monday, June 19, 2006

Thanks for your reply

In NHibernate 1.0.2 the lazy-loading feature is disabled by default so no proxies are used and this problem does not appear so you might have not encountered this problem ,also in the new 1.2-alpha there is a built-in automatic checker that checks if all methods in the class are declared virtual  to be compatible with the proxy pattern and this feature was not in 1.0.2, So in 1.0.2 you can use the lazy loading and no exceptions  will appear but the application will be buggey.

 

DavidDilworth replied on Tuesday, June 20, 2006

We are using 1.0.2 - I wasn't aware that there was a 1.20 alpha version.  But if it's an alpha then it's not ready for public release yet.

As for the issue of lazy-loading and proxies.  We are not using NHibernate lazy-loading because of the CSLA requirement to have a populated object graph on the server-side of the Data Portal.  That way the Data Portal can serialize the object graph for transmission back to the client.

We have taken the view that if we want to do lazy-loading, then it has to be done as multiple transfers across the Data Portal under our explicit control (i.e. using a lazy-loading pattern but with a BO that knows how to Data Portal itself).

I think it would be difficult to maintain a server-side NHibernate proxy to allow lazy-loading of your object graph.  I haven't really given it much thought, but it instinctively sounds like the wrong way to go.

kariem2k replied on Tuesday, June 20, 2006

Thanks very much for your help.

kariem2k replied on Tuesday, June 20, 2006

Oh by the way how do you manage the child collections and relationships.

DavidDilworth replied on Wednesday, June 21, 2006

We actually prototyped two different ways of managing child collections.

(1) Using a <set inverse="true"> mapping in the parent with a  <many-to-one> mapping in the child.

(2) Using a simple <set/> mapping in the parent with a simple <property> mapping in the child.

Using option (1) NHibernate automatically works out the FK relationship for you and puts the FK identifier into the right column in the child table.

Using option (2) you explicitly have to manage getting the identifier into the child yourself when you do the save.

We tested both options and they both worked fine.

Ultimately we have decided to go with option (2) and keep it under our control.  This decision was partly influenced by our need to generate some code automatically (using CodeSmith).  We felt the pattern needed for option (2) was easier to automate.

kariem2k replied on Wednesday, June 21, 2006

I am afraid that i did not put the question right,I meant  how do you convert the set type to the BusinessListBase type.

 

DavidDilworth replied on Friday, June 30, 2006

kariem2k,

Aha - yes.  Someone else has asked me this as well.

What we currently do is have two private member fields.  One is of type ISet (which is the one NHibernate uses to persist to/from the database) the other is a strongly typed List (derived from BusinessListBase).

But only the CSLA-based field is exposed via a public property.

Then inside the DataPortal_Fetch we loop over the ISet and call the Add() method to add the item into the strongly-typed CSLA list object.

The consumer of the BO then sees a strongly-typed CSLA style list, but the data is hidden inside an object that NHibernate knows how to persist.

ItsDubC replied on Tuesday, February 13, 2007

Are you using both lightweight and heavyweight representations of BOs as is the case in the ProjectTracker sample?  If this is the case and the ISet is a list of lightweight BOs, did you provide NHibernate mappings for the lightweight BOs as well or are you using HQL to load them?

DavidDilworth replied on Wednesday, February 14, 2007

@ItsDubC

We are in the process right now of making an NHibernate version of ProjectTracker.  I'm sure I've mentioned this on another thread somewhere else.

So what we are doing is changing the ProjectTracker.Library code base to use NHibernate as the ORM tool, instead of Stored Procedures.

The target goal for this mini-project is to get all the ProjectTracker User Interfaces working without changing any of the UI code - not a single line.

This seems to me to represent an example of the OO principle of Data Hiding.  The UI developer uses the classes in the ProjectTracker.Library, but has no idea how/where the data is coming from.

So, to that end, we are producing a ProjectTracker.Library.NHibernate.Dll that will completely replace the existing ProjectTracker.Library.Dll. 

However, the important thing is that we have NOT CHANGED any of the namespaces or classes for the entities that live inside the DLL.

It is still a Work In Progress and I'll post when we're finished.

Now if we could just get rid of those pesky bugs in our production applications that keep slowing us down ... Wink [;)]

DavidDilworth replied on Monday, March 12, 2007

I have some good news.

We have completed an NHhibernate version of the ProjectTracker example project.

I am currently corresponding with Rocky to see if I can get it released as part of the CSLAContrib project on CodePlex.

Watch this space!

kariem2k replied on Friday, March 23, 2007

Hi

I am now using CSLA beside the databinding  as a controller in MVC pattern.

NHibernate: for my domain model, the objects are POCO and works as DAOs.

CSLA: classes inherit from CSLA classes work as wrappers around the NHibernate's DAOs to support validation,databinding.

Why?

NHibernate has a different thinking of class design than CSLA .

So i have decided to make two designs one for data using NHibenrate, and another one for controllers that handles validation ,business behavior,then bind them to the view using CSLA.

So ProjectInfo class will be like.

class ProjectInfo : BussinessBase<ProjectInfo>

{

private ProjectDAO m_ProjectDAO = null; //ProjectDAO is NHibernate POCO

public string Name

{

   get{

CanReadProperty(true);

return ProjectDAO.Name;

}

set

{

CanEditProperty(true);

if(ProjectDAO.Name != value)

{

ProjectDAO.Name=value;

PropertyHasChanged();

}

}

......................

//Data Portal will use NHibernate Sessions to load and save data from ProjectDAO.

......

}

}

Notice that ProjectDAO will contain all the information about the entity and will be used in both Project and ProjectInfo(will have some properties from the DAO) classes.

IMHO this will give a very good seperation between the UI and Bussiness behavior and the data itself, Also will enable lazy loading in NHibernate because DAOs will not inherit form any class and will not have any Non-Virtual properties also collection lazy loading will not be a problem because the child collections will be simple IList<> not typed collections which NHibernate does not support,And about serialzation and CSLA must know all of the obbject graph before serialization you can access all properties in the DAO to load them first before serialization, I did not try serialization and remoting but i think it that would be the way to go.

Also you can combine two NHibernate DAOs in one CSLA class using composition pattern.

I don't know about remoting with this approach but i think it would no problem when using it, except caching i think.

Sorry for enlargement.

Thanks

burmajam replied on Sunday, March 25, 2007

Hi,

This approach looks very interesting with fields in NH DAO class and properties in the CSLA BO. Can you give us some example how did you do lazy fetching? I'm planing to make my next web project using CSLA and NHibernate, but I have to be sure that I can use everything I did so far with plain CSLA + ADO approach and I have to make decision very fast ... 7 days max.

Bayu replied on Monday, March 26, 2007

Hi Kariem2k,

Your idea is quite interesting!

But I was wondering if your design would hold also in more complex scenario's than your ProjectInfo/Project/ProjectDAO sample.

You see, in your example both use-case driven design and data-driven design arrive at the same record of project data. One thing is for sure: your ProjectDAO allows for much more straightforward caching.

Now let's consider the following example:
- I have Customers with Contacts (parent-child relationship established through foreign key on Contact)
- I have also have my own Employees (root-level objects)
- And I have a Outlook-like interface that asks for a list of all Persons (contacts + employees) to load the addressbook

My database design is nicely normalized as follows::
- Customer table (let's ignore this one in the remainder)
- Person table that stores all fields that are shared by Employees and Contacts (like name, email, ...)
- Contact table that extends Person with some Contact-specific fields and of course a foreign key to Customer
- Employee table that extends Person with some Employee specific fields (e.g. JobTitle, Department, ...)

While writing this I am getting the feeling that your proposed method with DAOs could make this work wonderfully ......

Could you describe how you would propose to satisfy the following needs with your solution?

- ContactList should be fetchable by CustomerID
    - involves an inner join on Person
- EmployeeList is top-level, so no params
    - also involves an inner join on Person
- PersonList is also top-level
    - no joins, just deals with the Person table

Let's see if we can take this one down with the benefits mentioned by you!

;-)

Thanks for your ideas,
Bayu

kariem2k replied on Monday, March 26, 2007

Hi

Thanks for your comment :)

First, The DAOs

Use NHibernate inheritance support, the most suitable stratgy for your case is the "table per subclass" stratgy.

                       ----------------- Contact

Person < ------

                       ----------------- Employee

Second, CSLA

   -ContactList: In GetContactsByCustomerID method use nhibernate's HQL "from Contact c where c.Customer.ID = 1" and fill CSLA's ContactInfo BO with each Hibernate's DAO.

  -EmployeeList: In GetEmployees method use ordinary session.Get method and fill CSLA's EmployeeInfo BO with each Hibernate's DAO.

  -PersonList: In GetPersons method use ordinary session.Get method and fill CSLA's PersonInfo BO with each Hibernate's DAO.

NHibernate will handle all inheritance functionality for you.

HQL will help you in CSLA's behavioral design. 

I hope i have answered your question.

Thanks

Bayu replied on Wednesday, March 28, 2007

Right,

No too much of a challenge there in the end I guess. ;-p

In an earlier post you mentioned the difference between use-case driven design for Csla objects vs the data-driven design for the DAOs.

This example and your solution to it nicely show the following benefits I think:
- Person data is defined only once in DB and hence only once in your PersonDAO object
- Contact/Employee simply inherit from this and there you have your 'data inheritance'
- authorizaion and validation is still use-case driven and defined in Csla objects that wrap the DAOs

To have a Csla class for Person with sub-classes Contact and Employee is more cumbersome:
- fields of Person may have to be validated differently based on use-case, so Employee/Contact might have validation rules for properties that are defined on Person
- similar for authorization, whether users may or may not modify properties is typically use-case based

So: I very much like your DAOs  for the aforementioned reasons.

But I also see 2 obvious downsides:
- performance, values from your DB are copied into your DAO and then all Csla properties wrap the DAO. It would need some testing and measuring to get a good impression of the performance costs. Also, these costs are partily compensated for by the caching possibilities. Although caching most benefits dp_fetch execution time while most of the costs will be in the property accessors.

- maintainability, I would not use DAOs until I have a codegen (currently still hand-crafting a lot)

Regards,
Bayu

kariem2k replied on Wednesday, March 28, 2007

Sure there will be a little performance degradation but it won't come from property accessors (It will be soo neglectable) but it will come from NHibernate itself (reflection,Dynamic sql generation,Creation of proxies).But every thing comes with a price right? The flexbility and easiness vs performance is always the issue in programming  (Like OOP vs structured programming  ;) ,After all depations saying that Structured programming is faster than OOP you will find the performance difference is really neglectable ).

But don't forget you will have also some easy performance boost from nhibernate,Like lazy-loading, Solution to the famous N+1 selects for grand children in CSLA, and caching of course.

Finally,IMHO using Nhibernate with CSLA is much more maintainable than using CSLA only.

Here is the way i use NHibernate:

  1. I create hbm mapping files,Describing the object and relational model even the database indexes.
  2. Make Nhibernate generate the Database from hbm files i have created (On any DBMS Sqlite,Sql Server,Oracle,etc... all of them are generated from only the hbm files with no mentionable changes,only tweaks for performance like disabling Out-Joins on Sqlite and enabling them on sql server) unless you are working with legacy data.
  3. Using simple custom CodeSmith templates to generate DAO POCOs from the hbm xml files, I use that templates untill NHibernate's Hbm2Net be able to generate generics.

If You notice that i did not touch my CSLA use-case driven classes,only if i am adding or removing properties,Also i use UML for describing the dependancy between CSLA classes and NHibernate classes.

So Nhibernate will save you the Sql statments and stored-procedures writting, Creation of the database (IMO Xml mapping files are more describing to object and Relational models than DDL or Tables in  any GUI database manager.) 

Thanks

 

DavidDilworth replied on Thursday, May 03, 2007

I can (at last) announce that there is now a ProjectTracker.NHibernate example solution on the CSLAcontrib site on CodePlex.

Can I suggest that all future CSLA / NHibernate questions (especially those related to the ProjectTracker.NHibernate solution) are posted on the CslaContrib forum.

Thank you all for your patience and support.

PitDog replied on Wednesday, June 21, 2006

How have you found this approach? I have used Hibernate in the Java world to handle ORM however I found it to be very cumbersome in the small to mid sized projects. It was almost something we needed to define a role for on our project. Not to mention most developers just said, "Why can't we map the data ourselves?"

At the start of most projects I am on this sits in the back of my mind. However I usually decide against it. I would be interested in how you feel about it.

DavidDilworth replied on Friday, June 30, 2006

PitDog,

I can see why developers would ask the "why can't we map the data ourselves" question.

The counter-question to that is "Why do you want to spend your time writing simple data mapping code instead of writing something else instead?".  Data mapping code is surely one part of the overall development process that can be more automated (even code generated)?

We've chosen to use the NHibernate.Mapping.Attributes extension DLL on our project, as we felt it had a real benefit.  So all we now do is simply attribute the private member fields that we want to persist and that's it.  NHibernate does the rest.

I admit that there was an initial learning curve to get over to actually understand what NHibernate was doing and how to get it to do what we wanted.  But after that it's been good so far.

All I can say so far is that everything we have tried to do with NHibernate, it has been able to deliver.  The guys behind it (and Hibernate of course) have clearly put a lot of effort into it to make it as functional and extensible as possible.

Copyright (c) Marimer LLC