NHibernate with CSLA

NHibernate with CSLA

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


Fabio posted on Thursday, May 11, 2006

What about to use NHibernate to persist BO ?
Regards
Fabio.

razorkai replied on Thursday, May 11, 2006

Hi Fabio

I believe there has been several conversations about this in the old forum.  Go to http://www.searchcsla.com/Search.aspx  and try searching for NHibernate using the Search Messages button.  You should get back a load of threads to look through.

HTH

John.

DavidDilworth replied on Monday, May 15, 2006

Check out this link on the old search site:  http://www.searchcsla.com/Details.aspx?msn_id=25534

We are currently using NHibernate with CSLA for our first project, which involves the addition of a Web Services interface to our existing application.

JTWebMan replied on Thursday, July 20, 2006

I found that when you mix NHibernate and CSLA you can sub class a good amount of the CSLA. I am still working out the kinks but I have some workable object now. I did find a better way to map fields to Me or this.

    Protected Sub FetchObject(ByVal session As NHibernate.ISession, ByVal value As T)
Dim MyType As Type = Me.GetType()
For Each field As FieldInfo In MyType.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic)
field.SetValue(Me, field.GetValue(value))
Next
End Sub


Then you can just call:

FetchObject(FetchObject(session, CType(session.Load(Me.GetType, _orderID), Order))


Do you see any issue with this? JT

DavidDilworth replied on Friday, July 21, 2006

JT,

I don't quite see what you're trying to achieve with your code.  NHibernate automatically puts the values from the DB into the fields for you.  Unless I misunderstand your code.

Check out this code fragment I added on another thread.

It shows a very simple usage of NHibernate loading the current instance, using session.Load(this, identifier).

You don't need to manually map the data into the fields.  That is what NHibernate will do for you, if you give it an appropriate mapping.

zythra replied on Wednesday, May 17, 2006

I've been using NHibernate on a project and have been ramping up on CSLA to use on another project.  I'm curious why you would want to use the two together.  Using CSLA vs NHibernate is in many cases based on personal preference and/or architecture needs, but I am very curious on your motivation to combine the two.

guyroch replied on Wednesday, May 17, 2006

CSLA and NHibernate, or any ORM for that matter, both have completely different objectives. 

CSLA make heavy use of the "domain" driven objects that encapsulate business rules and makes no attempt whatsoever to have an object that matches a database table.  The 2 are completely different. 

An ORM such as NHibernate tend to focus on the database schema and creates a one-to-one relationship model in that 1 table will end up as one business objects.

The advantage of using an ORM with CSLA, or any business object oriented framework, is that you can code you business object as per the business expect them to appear while not really caring how the data gets persisted in the database.  The other benefit is that you can quickly, or should I say more easily, adapt you business object to persist to an other data source such as Oracle or Firebird just to name a few.

The other advantage is that _most_ ORM will generate a “typed” object for each database objects such a table or a view.

Hope this helps

 

DavidDilworth replied on Thursday, May 18, 2006

I agree with Guy's comments - the two technologies are complimentary.

CSLA gives us well constructed Business Objects with rules and validation and the ability to surface them to a variety of different UIs (i.e. WebForms, WinForms, Web Services).

NHibernate gives us the ability to mark-up (with attributes) our BOs and persist them in any supported database engine (e.g. MS SQL Server, Oracle, MySQL).

They are doing two slightly different jobs and each meets a different requirement for my project.

In our case, we don't need to override the DataPortal_Fetch() in our BOs and provide all the mapping from the SafeDataReader to private member fields. 

All of this is done automatically by NHibernate in our two base classes which inherit from Csla.BusinessBase and Csla.ReadOnlyBase respectively.

zythra replied on Thursday, May 18, 2006

Thank you Guy and David, that makes much more sense.  I have just barely broken the surface with CSLA and hadn't gotten far enough to realize that it did not handle ORM.

This is quite intriguing to me now.  So I gather that you have NHibernate handle all of your CRUD while CSLA provides your data validation, business rules, etc.

Very cool.  I currently generate code for NHibernate, anybody out there generating coupled NHibnernate and CSLA?

pvanroos replied on Monday, June 26, 2006

Hi David,

I'm interested in what you're doing with NHibernate.  You're basically bypassing the CSLA DataPortal framework and utilizing NHibernate for your ORM operations instead?  Yes?  Any issues that you've come up against? 

I'm using CSLA 2.0.2 right now, but I'm thinking about swapping out the ORM code and plugging in NHibernate.  I've never used NHibernate but I understand what it does and how it works.  Are the productivity gains that significant to justify such a decision?

Also, I have one more issue I would like to hear you weigh in on.... With .NET 3.0 and Linq, will NHibernate become irrelevant?

Thanks,

Paul

DavidDilworth replied on Friday, June 30, 2006

Paul,

We're not bypassing the DataPortal framework - we still want mobile objects.  What we've done is replaced the ORM operations inside the DataPortal_xyz with NHibernate functionality, instead of ADO functionality.  So we use NHibernate Sessions instead of SQL connections.

One of our goals behind the choice for using NHibernate was to achieve database indepenence, so we are not tied to a specific vendor.  This may, or may not, be a consideration for you.

In terms of productivity, we have seem some benefits as we use the NHibernate.Mapping.Attributes extension DLL to simply attribute the private member fields we want to persist.  That works really well and is easy to fit into a code generation template (if needed).

As for .NET 3.0 and Linq?  Well I'm not sufficently familiar with either technology to comment on them just yet.

I'm thinking of converting ProjectTracker to use NHibernate to demonstrate its use.  Is that something you (or anybody else) would be interested in?

PitDog replied on Friday, June 30, 2006

Yes... Very much.

ajj3085 replied on Friday, June 30, 2006

DavidDilworth:
I'm thinking of converting ProjectTracker to use NHibernate to demonstrate its use.  Is that something you (or anybody else) would be interested in?


I would be, but only because I've been too lazy so far to look into NHibernate myself. Wink [;)]

ryancammer replied on Saturday, July 01, 2006

nhibernate has a little bit of a learning curve when you first start using it, but once you get it, there's no easier way i can think of to persist your BO's.

that said, we won't use it because it generates ad hoc sql, and there's a big difference between granting exec permissions on a sproc, and granting permission to execute sql statements. we're using ibatis instead (though i still wrote nhibernate mappings for my current project as well, just because).
 however, we're very interested in linq.

Markus replied on Saturday, July 01, 2006

DavidDilworth:

I'm thinking of converting ProjectTracker to use NHibernate to demonstrate its use.  Is that something you (or anybody else) would be interested in?



very interested.

burmajam replied on Tuesday, July 04, 2006

I am also interested in that project. How can I get it?. One more question. Did you try NHibernate with MySQL?

DavidDilworth replied on Tuesday, July 04, 2006

It's not available yet, we haven't done the conversion.  I'll post as soon as it's available.

We haven't tried NHibernate with MySQL yet, although we are aware that there is support for it.

colinjack replied on Wednesday, August 09, 2006

My company are planning to use NHibernate with CSLA but we want our business (domain) objects to be persistence ignorant and don't need the data portal approach. I was thus thinking of ripping out this functionality. Does this sound like a sensible approach?

DavidDilworth replied on Thursday, August 10, 2006

I'm not quite sure what you mean by "persistent ignorant", perhaps you could clarify that.

As for ripping out CSLA functionality, would it not be better to leave it in and just not use it.  If you don't need to use the Data Portal, then just don't use it.  Set your configuration to use a connection directly to the database.  The BOs will only be "mobile" if you sert up the config to work that way.

I say this from a maintenance point of view.  It will be much easier to take future CSLA updates "off the shelf" if you haven't changed the code.

ChristianPena replied on Thursday, August 10, 2006

I would be interested in seeing ProjectTracker using nHibernate as well. I am using nHibernate for a hobby project but using CSLA at work. I would like to use CSLA for the hobby project without giving up what I have so far.

colinjack replied on Monday, August 14, 2006

All I mean is that our domain objects won't, directly or indirectly, access anything that handles persistence. So you won't be able to call customer.Save(), instead it will be the process layer that will put NHibernate and the domain classes together.

How easy it is to do that will, I guess, depend on how many of the CSLA base classes are implementing methods related to the data portal.

Your probably right, I will just configure it not to use the Data Portal so thanks for the advice.

burmajam replied on Thursday, January 25, 2007

It's been few months since my last posts and detailed browsing on this forum. Shame on me Embarrassed [:$]. But still I've been using CSLA in the meantime, and I-m quite happy with it. But now I'm in a need of DB independent ORM with CSLA, and thought (again) of NHibernate. Is there any sample? What about translation of PtojectTracker on NHibernate?

 

burmajam replied on Thursday, January 25, 2007

As I said, shame on me. Just after posting previous message I saw the answer on the other thread. Anyway, I think that David still posted some key concepts. Thanks David. So, we'll have to do something on our own now I guess Smile [:)]. Sorry again for posting before reading.

 

ItsDubC replied on Wednesday, January 31, 2007

I've been trying to integrate CSLA w/ the NHibernate 1.2 beta and have only been able to get it to work with lazy loading off.  Anyone know why?  Also, I seem to remember David using the NHibernate mapping attributes contrib to avoid having to generate xml mapping files.  I'm wondering if there's any significant performance hit in doing it this way, especially since the documentation for the mapping attributes contrib says this at the very end:

In the design of this project, performance is a (very) minor goal :) Easier implementation and maintenance are far more important.

DavidDilworth replied on Friday, February 02, 2007

The performance hit is due to the fact that if you mark up your classes with NHibernate Mapping Attributes, you need to reflect them out of the assembly to create a mapping file.  There is a standard way to do this shown in the example code using in-memory serialization.

Once you have reflected out the correct mapping file, you are at the same point as if you had created the mapping file by hand in the first place.  The mapping file is then used to create an NHhibernate session factory.

So (in my opinion) performance has been sacrificed for the sake of maintainability, as the code is self-documenting and the "mappings" are contained in the same source file as the class itself.  If you change the class source file, you change the mappings at the same time.

That is the point the author is trying to make in the sentence you quoted.

HTH.

ItsDubC replied on Friday, February 09, 2007

I agree.  Someone posted a comment somewhere else online saying that while NHibernate.Mapping.Attributes may decrease hardware runtime performance slightly, it greatly increases developer performance.  I liked that and decided to try doing an NHibernate load operation of a single BO using the traditional XML file and then loading the same BO using mapping attributes to see for myself if there were any significant performance issues.  While there was a noticeable (but not significant) difference in execution time, am I correct in my understanding that each subsequent operation using that BO will take much less time because the mapping file will have already been reflected out by the session factory?  If that is the case, then using Mapping Attributes is a no-brainer for me.

However, I'm still concerned about the lazy loading issue because I can foresee a situation in which a single BO will have hundreds of child objects who in turn have thousands of child objects and so on.  It'd be nice to be able to turn lazy loading on without having to make a lot of modifications to CSLA.

DavidDilworth replied on Monday, March 12, 2007

I have some good news for anyone interested in NHibernate.

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!

ItsDubC replied on Monday, March 12, 2007

Great news David.  I'm looking forward to seeing how you've implemented the "parent->child collection->child" relationships with NHibernate and which operations, if any, you've chosen to cascade.  Also curious to see if you're using a different way of deleting objects other than loading them first.  I was going to look into using HQL to delete objects without loading them first but haven't gotten to that yet.  Keep us posted!

DavidDilworth replied on Wednesday, March 14, 2007

Your curiousity is well directed. 

Actually, the implementation we used for the factory method Delete...() is to load the object first.  We then mark it as deleted and go off and start physically deleting stuff.

The rationale behind this decision was down to the fact that we have modelled the parent->child collection entity relationships as an NHibernate mapping.  Therefore, NHibernate "knows" what to do when you do a Fetch() within the scope of a single NHibernate ISession to get the full object graph.

When it comes to the factory Delete...(), NHibernate can't know what the "full object graph" is, unless it's already loaded.  Once it's loaded then it is very easy to delete the object graph.

This implementation also supports the deferred Delete concept as well.  The only difference being that the instance object is already loaded in memory.

There are examples of both these scenarios in the NUnit tests we've written, which will be included on the CSLAContrib project.

rbell replied on Friday, March 16, 2007

How do you suggest implementing a parent -> child collection relationship?  According to what I have read and experimented with, NHibernate allows one to map a collection of object by mapping to the interface equivilent (i.e. IList).  But in reality we want to map these collections to the CSLA implemented collection derived from Csla.BusinessListBase<T,C>.

I have found a way around this restriction by mapping the bag to a private property of IList and using the get and set to populate the collection derived from Csla.BusinessListBase.  It looks something like this:

Pets _pets;
public Pets UserPets
{
   get
   
{
      
return _pets;
   }
}

[Bag(3, Cascade = CascadeStyle.All)]
[
Key(4, Column = "LogonId")]
[
OneToMany(5, Class = "NHibernateSandBox.Pet, NHibernateSandBox")]
private IList hPets
{
   
get
   
{
      return (IList)_pets;
   }
set
   
{
      
ArrayList pets = new ArrayList();
      pets.AddRange(
value);
      
foreach (Pet p in pets)
      
{
         
if (!_pets.Contains(p))
            _pets.Add(p);
      }
   }
}

 This seems a little hacky to me but it works.  I guess another method would be not to use bags at all but instead pass a session object to the child collection and use HQL to fetch the children, etc.

rbell replied on Friday, March 16, 2007

How do you suggest implementing a parent -> child collection relationship?  According to what I have read and experimented with, NHibernate allows one to map a collection of object by mapping to the interface equivilent (i.e. IList).  But in reality we want to map these collections to the CSLA implemented collection derived from Csla.BusinessListBase<T,C>.

I have found a way around this restriction by mapping the bag to a private property of IList and using the get and set to populate the collection derived from Csla.BusinessListBase.  It looks something like this:

Pets _pets;
public Pets UserPets
{
   get
   
{
      
return _pets;
   }
}

[Bag(3, Cascade = CascadeStyle.All)]
[
Key(4, Column = "LogonId")]
[
OneToMany(5, Class = "NHibernateSandBox.Pet, NHibernateSandBox")]
private IList hPets
{
   
get
   
{
      return (IList)_pets;
   }
set
   
{
      
ArrayList pets = new ArrayList();
      pets.AddRange(
value);
      
foreach (Pet p in pets)
      
{
         
if (!_pets.Contains(p))
            _pets.Add(p);
      }
   }
}

 This seems a little hacky to me but it works.  I guess another method would be not to use bags at all but instead pass a session object to the child collection and use HQL to fetch the children, etc.

ItsDubC replied on Friday, March 16, 2007

I have taken pretty much the same approach.  My parent objects contain a public CSLA child collection as well as a private NHibernate collection, though I'm unsure whether my implementation is the best way of doing it:

[Set(11, Name = "NHChecklistItems", Cascade=CascadeStyle.Delete, Inverse = true, Lazy = false)]
[Key(12, Column = "ChecklistID")]
[OneToMany(13, Class = "PAO.BLL.ChecklistItem, PAO")]
private Iesi.Collections.ISet NHChecklistItems
{
      get
      { return _NHchecklistItems; }
      set
      { _NHchecklistItems = value; }
}

public ChecklistItems ChecklistItems
{
      get
      { return _checklistItems; }
      set
      { _checklistItems = value; }
}

So when I fetch the parent object, NHibernate populates NHChecklistItems w/ the child objects so all I have to do is copy those objects into ChecklistItems.  Then, before I do an NHibernate update, I clear NHChecklistItems and then populate it w/ the objects contained in ChecklistItems.  Again, I'm not sure if this is the best way of doing it but it works.

rbell replied on Friday, March 16, 2007

One thing I just found about this approach is that NHibernate does not mark the children as a child (normally by calling "MarkAsChild()") nor does it mark the children as old (normally by calling "MarkOld()").  So when copying the items from the NHibernate collection to the Csla collection, you have to somehow set those objects to as a child and as old.

Since those methods, in the base class, are protected, I just added a public method to the child class that allows the parent to pass in the item from the NHibernate collection and returns an object marked appropriately.

DavidDilworth replied on Monday, March 19, 2007

The approach we've taken is to have a private field that is used for the NHibernate mapping to read the data into during the DataPortal_Fetch() and then copy the references into the CSLA list after the data has been fetched.  This is done in an abstract generic base class.  I've included the key extract of the code below to show the idea.

This features a call to an Init() method on the BO, which allows the BO to mark itself as "old" or perform any other initialisation steps required.

Because this code lives in an abstract generic base class from which all lists inherit there's only 1 implementation of the "copy" from the IList to the CSLA list.

private void Add(IList theList)
{
    // Stop raising events while the list is modified
    RaiseListChangedEvents = false;

    // The IList contains "dumb" objects so they need to be cast to the correct type
    foreach (object abstractObject in theList)
    {
        // Cast the current item to the correct BO type
        C businessObject = abstractObject as C;

        // If the cast did not work then something has gone wrong
        if (ReferenceEquals(businessObject, null))
            throw new FrameworkException("Object of type '{0}' in NHibernateBusinessListBase '{1}' was null.", typeof (C)).ToString(), (typeof (T)).ToString());

        // Get each object to perform any initialization required on itself...
        businessObject.Init();

        // ...and then add it to the list
        Add(businessObject);
    }

    // Start raising events again
    RaiseListChangedEvents = true;
}

This is taken directly from the code that will be posted to CodePlex.  However, we've just had to move offices at short notice and putting the code up on CodePlex has temporarily taken a back seat for a few days.

TLingus replied on Thursday, April 19, 2007

That looks quite clean.  This is very exciting... the notion of leveraging the power of NHibernate from CSLA (not just in terms of database-independence, but also its concurrency model, etc.) is enticing to put it mildly!  I just want to join the chorus of those who very much appreciate your doing this and look forward to learning from your NH ProjectTracker example. 

Cheers!
T

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.

David

chuawenching replied on Wednesday, September 26, 2007

Just curious, how do you link this projects (csla and nhibernate) to the existing CSLA project's ProjectTrackercs?

When i donwloaded the cslacontr, I only see Test projects. Really like to see how it is actually implemented with User interfaces.

Thanks.

DavidDilworth replied on Monday, October 08, 2007

Sorry for the slow reply, but your email got "lost" in our system.

There is no change to the ProjectTracker UI code line.  That was the point of the changes.  All the changes made were "under the hood" so that the UI remained 100% the same.

Just replace the standard assemblies with the CSLA/NHibernate ones and everything should still work exactly the same.

mcnamara replied on Monday, March 24, 2008

Is nhiberate versions of ProjectTracker still available at codeplex? I couldn't find it in releases.

Thanks.

DavidDilworth replied on Wednesday, March 26, 2008

Yes it is still there included in the release - I just checked.

ozitraveller replied on Thursday, April 17, 2008

I have a question about concurrency. And I admit I have only just started to look at the PTracker sample. I notice that the timestamp fields have been commented out. Is this handled by NHibernate, or am I missing something?

BTW, nice job I was just looking for an example of Csla and NHibernate.

DavidDilworth replied on Friday, April 18, 2008

Look for an integer Version column and field in the code.  That is the way we handled optimistic concurrency the NHibernate.

ozitraveller replied on Sunday, April 20, 2008

Thanks David

rbell replied on Monday, March 12, 2007

I can hardly wait to see the NHibernate version of ProjectTracker! 

The ironic thing is that I spent a lot of time over the weekend experimenting and learning some of the ins and outs of NHibernate and my experimentation spawned several questions on the best way to integrate it into a CSLA project.  I remembered spotting this thread on this forum about a month ago and was going to ask you about the status of the ProjectTracker implementation.   I was thinking I was going to do a search to find the thread and to my suprize it was at the top of the list!

Copyright (c) Marimer LLC