Blending ORM with CSLA is like mixing oil and water to me

Blending ORM with CSLA is like mixing oil and water to me

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


Jijay posted on Tuesday, May 23, 2006

Hi, I'm using CSLA, and to tell the truth, I'm not quite sure how to deal with data access layer with it.
I tried to use ORM to gain benefit of its strong type, caching, performance, lazy-loading, reduced plumbing, rapid development, adaptive to changes, and all other benefits. But I found out that it is very hard to me to blend CSLA with CRM smoothly.

First, it's almost impossible to use ORM which requires inheritance to a base class.
Second, as the premise of CSLA suggest, the business object design should not be tied to any table in DB. Therefore, I use an approach where persistence objects are used only to fetch and manipulate information for business object. I build procedures to extract information in some ORM object (persitence objects) into a buiness object, then keep the persistence objects inside the business objects to support its data access.
But this approach apparently doesn't work well with n-level undo, serializable (if the ORM objects inherits an unserializable base class), and surprisingly requires unacceptably much manual effort on monkey job (something that CSLA was initially designed to reduced).

I'm realy glad if anyone could share what approach they use to work using ORM together with CSLA.
Thanx...

DavidDilworth replied on Tuesday, May 23, 2006

My view is that ORM and CSLA are complimentary technologies.  See my post on this thread regarding NHibernate.

As I see it, an ORM tool is responsible for getting data into and out from the database engine of your choice.

CSLA provides you with the ability to have mobile objects with business level validation that can be surfaced via a number of different UIs.

I don't have any problem with populating a CSLA business object using the NHhibernate framework in this way.

My objects inherit from the CSLA base classes and are not tied to any particular database vendor, but they are linked to tables within my schema (that's the Mapping part).

ajj3085 replied on Tuesday, May 23, 2006

I agree with David.

Your ORM layer is your data layer, which is consumed within your business layer (which is built on the CSLA framework) in the DataPortal_XXX methods.

I think ORM is a misnomer; ORMs generate objects which closely mirror the database, but your business objects will likely have quite a different structure.  To me, ORM just seems to be an object for maniuplating a table in a database, so that you don't have to worry about which specific database you're talking to.

So its ORM isn't so much a mapper as it is a database independant way to work with databases.  The 'mapping' from data world to business world would be handled by your business objects.

Andy

guyroch replied on Tuesday, May 23, 2006

Have you ever dream to have strongly typed objects that represent the database schema so that instead of doing

this._id = dataReader.GetString("CustomerID");

you could do

this._id = MyOrm.CustomerId;

...and get a compile error if you screw up instead of a run time error.  Also, if you change you database layer, your CSLA library will not compile until you fix the compile error thrown by the strongly typed object.

You see, CSLA and ORM are not like oil and water; they are very much complimentary to one another.  If anything one shouldn’t be used without the other.  Using an ORM will also allow you (or make it way more easier) to change to an Oracle database or Firebird, or any support database by you ORM.

Jijay replied on Wednesday, May 24, 2006

Mapping a business object using ORM is sensible, but is not quite an option for me, because as what Rocky suggested in his idea of CSLA, the use of ORM in BO violates at least 2 basic OO principle.
  1. Most ORM disallowes us to employ OO concept like inheritance and data-hiding.
  2. It makes our object to be relationally designed. It would be difficult to design the objects based on their business roles. It tends to normalize the objects by their data rather than by their behavior.
'guyroch' idea is the one I adpot. Yes, what I write in my previous post is basically the approach outlined by guyroch (this._id = MyOrm.CustomerId;). That snippet was what I called as procedure to extract info into BO. What needs to be highlighted is the fact that MyORM (and other persistence object, e.g.: DataReader) has to be in local scope, and not in instance scope. This means that the ORM object should be discarded each time it's used, and should be somehow reconstructed on another call.
However, that is usually not quite an easy task. You may notice that only a small part of the MyORM content extracted into BO. How do I managed the rest? This way, give me no clue how to gain benefits of the ORM itself, such as relations, lazy-loading, smart-update, cascade update/delete, and many more.

Below is a short illustration
public static BO RetrieveObject(Criteria criteria)
{
    ORM1 orm1 = ORM1Factory.Retrieve(BuildORM1Criteria(criteria);
    ORM2 orm2 = ORM2Factory.Retrieve(BuildORM2Criteria(criteria);
    return ExtractFromDbo(orm1, orm2);
}
public void Update()
{
    // Yeah, you somehow reconstruct your ORM objects here
    FillToORM1(orm1); // This should be rebuild all children objects & relations as well
    FillToORM2(orm2); // This should be rebuild all children objects & relations as well
    orm1.Update();
    orm2.Update();
}

public ChildList TheChildren // Load from ORM relation (Lazy-Load)
{
    get
    {
         if(this._theChildren == null)
         {
             // Somehow reconstruct ORM1 objects
            this._theChildren = Child.ConvertFromORMList(orm1.ChildOrmList);
          }
          return this._theChildren;
    }
}

Yeah, I'm a rookie in CSLA, so I realy curious how the heck the guys outthere manage their data-access in CSLA. So I really wonder in how you use nHibernate in CSLA. I really appreciate if you could share me the practice you usually use when working with ORM in CSLA, and what ORM you think suits CSLA best.
Thank you for any response.

DavidDilworth replied on Wednesday, May 24, 2006

As an example of what our BO code looks like, here is an extract from our abstract base class class called NhibernateReadOnlyBase.  This forms the basis for our ReadOnly BOs.  The only thing we have to do in our concrete BO class is mark the properties that are being persisted with an NHibernate specific attribute - NHibernate then takes care of the rest.

protected override void DataPortal_Fetch(object criteria)
{
 // Get an NHibernate session factory
 NH.ISessionFactory sessionFactory = Nfs.Nhibernate.Cfg.BuildSessionFactory(SessionFactoryKey);

 // Get an NHibernate session from the factory
 using (NH.ISession session = sessionFactory.OpenSession())
 {
  // Get the identifier required from the criteria
  object identifier = GetNhibernateIdentifier(criteria);

  // Load the current instance from the NHibernate session based on the identifier
  session.Load(this, identifier);
 }
}

DansDreams replied on Wednesday, May 24, 2006

Ok, I'd like to run this by you guys and see how it makes sense in the context of something like NHibernate.

I am envisioning a design whereby a business object knows only how to accept or pass an XML representation of its data.  The DAL (which could possible be an ORM or NHibernate??) knows how to get that XML DTO from the database.  The beauty I'm seeing here is that it is a fairly simple matter at that point to wrap something like a web service around the business objects.  No significant additional translation functionality or classes necessary, just another way the XMLDTOs get in and out of the BO.

RockfordLhotka replied on Wednesday, May 24, 2006

Dan,

I've been toying with something along this line. In the VB6 CSLA I used a structure to contain an object's data, and I'm thinking that perhaps a return to such a model (with the exception of child object references) is part of the overall solution. If you object keeps all its data (except child references) in a DTO (class or structure) then you have the means (with the XmlSerialize or DataContractSerializer) to easily convert that state into/out of XML.

Either that, or use DataMapper to easily copy the values into/out of the DTO - but that seems like an extra copy that may not be necessary if you are willing to always access your "fields" through a _state variable.

Instead of x = 10 you'd write _state.x = 10.

There is an impact here in terms of n-level undo, because this DTO would be treated as a single field in the object. However, as long as it is marked as serializable there's no issue - and marking it as serializable doesn't interfere with the XmlSerializer.

To me the primary drawback is that you have to declare/code the DTO, and it probably needs to be in its own assembly so it can be shared between your business assembly and your data assembly. On the other hand, you can use public fields (because you'll never data bind directly to the DTO) so that reduces the coding effort quite a lot Smile [:)]

DavidDilworth replied on Thursday, May 25, 2006

I think I see where you want to go with this idea and I've seen Rocky's response as well.

But I'm not convined that an ORM tool is what is needed to do this job though.  It sounds to me like you're talking about the DTO being an XML formatted object, or containing an XML object.  So the initial transformation that's needed is from relational data tables into structured XML.  That's not ORM (Object Relational Mapping), but perhaps something called XRM (XML Relational Mapping).  Yes that XML is part of an object (the DTO), but it's not a BO in the sense that we talk about them with relation to CSLA.

What NHibernate gives you is a way of mapping the relational data tables directly into the private member fields of your BO.  Or you can go through the public properties if you want instead. 

So we're using it to replace the kind of code you'd traditionally write in your DataPortal_Fetch(), such as:

_id = dr.GetGuid("Id");
_name = dr.GetString("Name");
_started = dr.GetSmartDate("Started", _started.EmptyIsMin);
_ended = dr.GetSmartDate("Ended", _ended.EmptyIsMin);
_description = dr.GetString("Description");

which instead becomes a single call in the base class:

session.Load(this, identifier);

(see the fuller example in my earlier post).

For the DTO concept to work then the definition of the object should be driven by the XSD schema definition in the web service via the WSDL, which defines your contract with the outside world.

We're currently running a Web Service project using a technique called Web Services Contract First (WSCF).  This starts with the contract (i.e. interface) you agree with the outside world for your Web Service.  We've found that going down this route you then need facade classes to bridge between the class definitions used by the Web Service and those of your BO.  These are somewhat analagous to the "facade" classes in the ProjectTracker Web Services example, where the code maps the data between the BO class and Web Service class.  In our case, the two are not exactly 100% the same - things are never that easy Wink [;)]

BTW, good to see you again on the new forum Dan  Smile [:)]

DansDreams replied on Thursday, May 25, 2006

Rocky, that's taking it in a slightly different direction - or at least it comes from a slightly different motivation - but I've thought about that too.  I've liked the benefit this decoupling offers in the databinding.  There would be no more need to think in terms of getting a new object from the save operations and having to unbind and rebind in the UI.  This data container would just be replaced in the BO and nobody higher up would know any better.

While the undo could still work as is, wouldn't it be better to take advantage of the fact that we would then know that what we want to save as "state" is precisely and only this state object?  No need to wade through all the properties of the BO and do all that checking and filtering.

David, I think the ORM still applies in that case as you still need data access code to get the data into that state class.

I think what I was describing is a slightly different thing, or maybe it's a part of the bigger picture including this concept.  Considering Chapter 11, what if we move some of the facade concept into the BO class itself?  For example, what if we had something like:

private DataPortal_Fetch(SimpleCriteria criteria)
{
   ProjectData[] data = SomeDAL.GetProjectList(criteria);
   loadFromDataArray(data);
}

private void loadFromDataArray(ProjectData[] dataArray)
{
   // Load from the ProjectData array as demonstrated in Chapter 11
}

Then it's easy peasy to add a factory method

public static ProjectList LoadProjectList(ProjectData[] dataArray)
{
   loadFromDataArray(dataArray);
}

And that in turn makes the web method to add Projects really just a simple pass through if it accepts an XML structure representing a list of ProjectData data.  Ok, I'm sort of typing this thinking out load, but I think you'll see what I'm driving at.

Does this really provide a development productivity gain, or a loss because of increased complexity?  Would it usually be the case that enough BOs need to be exposed through web services that it makes sense to do this as a general rule, or does it make more sense to just deal with what needs to be exposed via WS on a case by case basis?

RockfordLhotka replied on Thursday, May 25, 2006

Dan, I think you misunderstand what I'm saying. I think you and I are in agreement - that DTO would only be used to load the object, it would not be exposed directly to the UI.
 
All I'm suggesting is that you'd replace your use of private fields in the object with the DTO itself - thus avoiding having to copy the data into/out of the private fields. And that would have some impact on the way undo works, because then your DTO would be a single (THE single) field in your object and it would be serialized as a blob. In most cases I think the functionality would be identical, but without further thought it is hard to say for sure.
 
I think overall that I prefer the idea of mapping the data into/out of the DTO - possibly using an enhanced version of DataMapper - is the best approach, even though it does involve some overhead. Apparently this type of overhead is considered trivial, because looking at LINQ, that's what Microsoft is doing all over the place. :)
 
Rocky


From: DansDreams [mailto:cslanet@lhotka.net]

Rocky, that's taking it in a slightly different direction - or at least it comes from a slightly different motivation - but I've thought about that too.  I've liked the benefit this decoupling offers in the databinding.  There would be no more need to think in terms of getting a new object from the save operations and having to unbind and rebind in the UI.  This data container would just be replaced in the BO and nobody higher up would know any better. [...] 

DansDreams replied on Thursday, May 25, 2006

Rocky, I agree with all that 100% and I'm seriously considering this design for the major project about to launch here.  I pretty much never give much concern to overhead in CRUD contexts since even theoretically or otherwise significant hits almost always get totally buried in the data access.

I think I'm still suggesting I guess one slight addition from the public perspective, which is that coding this way in a version-safe manner against a DTO would enable that DTO to easily come in the form of XML from a web service, and I'm pondering the potential value of that.

One of the back-end vendors here has some significant web service capabilities.  When I ask for a list of contacts I get something like

<ContactContainer xmlns="http://corrigo.com/contact.xsd">
  <Contact ID="13373" CustomerNumber="101781" Action="update"  FirstName="Joyce" LastName="Brothers" Phone="555-1212"/>
</ContactContainer>

And to update that contact I just send that XML back to the update method with the changes.  To add a new contact or delete one I do the same thing but change the Action to "add" or "delete" respectively.  It's the kind of behavior I believe you had in mind in Chapter 11 when speaking of the service-oriented design option.  It works very well.

It just strikes me that XML like that is functionally equivalent to the DTO in the design we're discussing - which begs the question why not handle both with as much of the same code as possible?

Or am I just seeing things as way too simplistic because I haven't actually pounded out this code?

RockfordLhotka replied on Thursday, May 25, 2006

I think the primary concern I have is that dealing with XML directly is a PITA (imo anyway). Until XLinq arrives, I'd much rather conver the XML into proxy objects (DTOs) so I can work with the objects and then convert them back into XML for transmission. This is what the XmlSerializer is for, and I think it does a good job.

And yes, this is exactly the kind of thing I am talking about in Chapter 11. While this is arguably not "service-oriented", what you are talking about doing is treating the external services as "XML stored procedures", and I totally buy into that as a sound philosophy on which to build an app with CSLA .NET.

So whether you directly interact with the XML or use DTO proxy objects doesn't matter - that's plumbing. The architectural concept itself is entirely sound - because you can simply envision the XML/DTO taking the place of ADO.NET DataReader and Command objects.

What I'm contemplating is enhancing DataMapper to more easily support the DTO concept, with the intent of formalizing support for an external DAL that returns and consumes DTO proxy objects - whether they be populated by ADO.NET, a web service, DLinq or some future data access technology.

pelinville replied on Thursday, May 25, 2006

Rocky, are you avoiding the copy to/from the DTO to limit the extra work of the developer or is there some other reason?  Performance? Scalability?
 
I do this but the "copy" code is done in code generation.  The DAL can return either a DataReader or a DataTable and the business object fills itself by checking the type of the object returned. 
 
I ask to make sure there is something I don't understand.

RockfordLhotka replied on Friday, May 26, 2006

The copy to/from the DTO has (I think) two drawbacks: extra work for the developer (which can be offset by code gen), but more importantly performance.
 
This is the same reservation I have around using a DataSet to load your objects. ADO.NET copies the data into the DataSet and then you copy it from the DataSet to your fields. As compared to a DataReader where you copy the values directly into your fields (saving one whole copy process).
 
A DTO, or ORM, cause the same double-copy as with a DataSet. Which is why I've personally resisted that approach when possible.
 
But I'm starting to cave in :)   It is very clear that most people, including Microsoft itself, just don't worry about extra copy operations. It may be the case that I've fallen for a premature optimization trap and should just quit worrying about it.
 
Rocky


From: pelinville [mailto:cslanet@lhotka.net]
Rocky, are you avoiding the copy to/from the DTO to limit the extra work of the developer or is there some other reason?  Performance? Scalability?
 
I do this but the "copy" code is done in code generation.  The DAL can return either a DataReader or a DataTable and the business object fills itself by checking the type of the object returned. 
[...]

malloc1024 replied on Friday, May 26, 2006

Why not use a separated interface approach instead of DTOs?  This will allow you to load the object directly from the DAL.  The trick, use explicit interfaces instead on implicit interfaces.  Create an explicit interface for each object and add them to the DAL.  Have each object implement their respective interface.  Add a LoadingFromDAL flag to each interface.  Setting this flag before loading an object will allow you to load your object directly without evoking broken rules, MarkDirty etc.  Further, it also allows you to load ReadOnly properties.  Using explicit interfaces will also allow you to load private properties from the DAL.   The only way to access these private properties (not including reflection) is through casting to the interface. However, since the interface resides in the DAL, the presentation layer will never be able to access these private properties.  Using explicit interfaces solves most of the problems that are associated the separated interface method.  Does anyone see any potentail problems with this?

pelinville replied on Friday, May 26, 2006

Malloc
 
Wouldn't that tie the BO's to the DAL to much?
 
For example I have Project A and B.  Project B needs to add some fields so the interfaces must now be updated.  This will break Project A when it tries to get it's data because of serialization issues, no?
 
Maybe I just don't understand so here are a couple questions.
 
1. What is the difference between an implicit and explicit interface?  Do you mean implicit as the interface a Class has vs explicit as in  "Public Interface XYZ"?
2. Are you saying the the DAL returns, say, an IPerson and because your BO is also an IPerson it exoses the IPerson from the DAL through it's own implementation of IPerson?
 
Please explain more.

RockfordLhotka replied on Friday, May 26, 2006

Explicit/implicit is a concept in C# due to the way the language implements interfaces. Explicit is functionally equivalent to the VB6 idea of having a private method implement the interface, while implicit is similar to the VB6 idea of having that method be public in scope.
 
VB.NET and VB 2005 are (I think) a bit more explicit in both cases:
 
Public Class X
  Implements Y
 
  ' like C# implicit
  Public Sub Foo() Implements Y.Foo
    ' implement method here
  End Sub
 
  ' like C# explicit
  Private Sub Bar() Implements Y.Bar
    ' implement method here
  End Sub
 
End Class
 
(If you didn't catch the hint of attitude, it is my view that this is the one area where the C# language just got it totally wrong, and where they should have learned from VB6 and gone with a more explicit and visually clear way of implementing interfaces rather than doing a minor tweak of the (lame) VB6 approach...)
 
But in the end it doesn't matter about the syntactic difference - the concept is sound. And to avoid tying the business library too close to the DAL, you could have a third assembly to contain the interfaces - referenced by both the business and data assemblies, but not by the UI.
 
Back to the point of the original concept:
 
Public Class X
  Implements Y
 
  Private _foo As String = ""
 
  Public Property Foo() As String
    Get
      CanReadProperty(True)
      Return _foo
    End Get
    Set(ByVal value As String)
      CanWriteProperty(True)
      If Not _foo Is value Then
        _foo = value
  
      PropertyHasChanged()
      End If
    End Set
  End Property
 
  Private Property Y_Foo() As String Implements Y.Foo
    Get
      Return _foo
    End Get
    Set(ByVal value As String)
      _foo = value
    End Set
  End Property
 
End Class
 
Notice that the public Foo property is like normal, while the private Y_Foo (or whatever you choose to call it) bypasses all the normal processing.
 
This is (I think) a great approach if you are using a code-gen tool - otherwise it virtually doubles your effort to implement each property. Though I suppose snippets would reduce that effort as well, so maybe it isn't so bad either way.
 
As long as the interface is in its own assembly you should be reasonably decoupled from the DAL, so that should be OK too. With the overall understanding that adding/removing a property means updating three assemblies.
 
Rocky

ajj3085 replied on Friday, May 26, 2006

Hi Rocky,

Just curious, why is the C# way of explicit implemention wrong?

    public class Class1 : IClass {

        #region IClass Members

        void IClass.MySub() {
            throw new Exception( "The method or operation is not implemented." );
        }

        #endregion
    }

    public interface IClass {
        void MySub();
    }

You can still see that MySub is an explicit interface because its prefixed by IClass.

I think it makes sense that its private too; if you think about it, MySub should NOT be visible for explicit implementations until you cast the object to the interface.  So the method is private until you cast it to the interface, at which time it becomes public. 

Just my thoughts.

Andy

RockfordLhotka replied on Friday, May 26, 2006

The explicit approach is acceptable, other than that you should be able to mark it as protected, because that is a common requirement.
 
It is limited, in that multiple interfaces require multiple method implementations - often routing to the same common implementation method - where VB's approach allows you to explicitly map interface methods to any class method that has the same signature. So if you have two interfaces with a Foo() method in VB you can have a single implementation method for both.
 
My complaint is with the implicit implementation. You can't look at the code for a method and know that the method implements something on an interface. You have to look at the class, see what interfaces it implements and then compare the method signature to all methods on those interfaces. That's the part that I find particularly sloppy. For an otherwise highly explicit and self-explanatory language, this kind of magic seems very inconsistent to me.
 
Rocky


From: ajj3085 [mailto:cslanet@lhotka.net]

Just curious, why is the C# way of explicit implemention wrong?

pelinville replied on Friday, May 26, 2006

Ahh, now it is coming back... horribly.
 
I had to take over a c# project a couple of years ago and most classes implemented 3 or 4 interfaces.  Curly braces and semicolons and all the other c#isms no problem.  Even grew to like it. But that implicit interface implementation (didn't know it was called that) drove me nuts!  Maybe it wouldn't be so bad if I was in on the ground up but coming in at the end (and the guy leaving) made that stuff a nightmare.  It took forever to figure out what was doing what. And the classes that implemented interfaces that had the same member names or if you wanted to inherit from a class that happened to have a member with the same signature.....  AHHHHHHH! 
 
 
I agree, the VB.Net way makes things much clearer.  Call me a nooby mort all you want, I like the extra verbosity.
 
(one other thing that killed me.  There where some methods that where exactly the same except for the names where different case one protected the other public.  Try inheriting from that in VB.  I know, bad developer and not the language. But still.)

malloc1024 replied on Friday, May 26, 2006

Rocky,

Couldn’t you expose the same property to the UI that you used to load from the DAL? You can set a flag to avoid evoking the business rules, MarkDirty etc.  This way you only have one property to take care of. 

Below is some pseudo code.

////////////////////////////////////////////////////////////
//Interfaces located in DAL or Seperate Assembly
public interface ILoadFromDAL
{
    bool LoadingFromDAL
    {
        get;
        set;
    }
}

public interface ICustomer : ILoadFromDAL
{
    string FirstName
    {
    get;
    set;
    }

    string LastName
    {
    get;
    set;
    }

    string MiddleName
    {
    get;
    set;
    }
}

////////////////////////////////////////////////////////////
//Business Layer
public class BusinessBase: ILoadFromDAL
{
private bool mLoadingFromDAL;
  
bool ILoadFromDaL.LoadingFromDAL
    {
        get
        {
            return mLoadingFromDAL;
        }
        set
        {
            mLoadingFromDAL = value;
        }
    }

    //Add  rest of BusinessBase
}

public class Customer : BusinessBase,  ICustomer
{
    private string  mFirstName;
    private string mLastName;
    private string mMiddleName;

    private string FirstName //Note that it is Private
    {
        get   
        {
            return mFirstName;
        }
        set
        {
            mFirstName= value;
            if(mLoadingFromDAL==false)
            {
            //call broken rules
            //MarkDirty
            }
        }
    }

    public string LastName //Note that it is Readonly
    {
        get   
        {
            return mLastName;
        }
        set
        {
            if(mLoadingFromDAL == true)
            {
                mLastName= value;
            }
            else
            {
                throw new Exception("This property is readonly.");
            }
        }
    }

    public string MiddleName //Note that this is public and exposed to UI
    {
        get   
        {
            return mMiddleName;
        }
        set
        {
            mMiddleName= value;
            if(mLoadingFromDAL==false)
            {
            //call broken rules
            //MarkDirty
            }
        }
    }

    public void Load()
    {
        CustomerDAL.Fetch(this);
    }
}
   

////////////////////////////////////////////////////////////
//DAL
public class CustomerDAL
{
    static public void Fetch(ICustomer obj)
    {
        obj.LoadingFromDAL = true;
        obj.FirstName= "Foo";      //note that it is private
        obj.mLastName= "Foo1";  //note that is is read-only
        obj.mMiddleName= "Foo2"; 
        obj.LoadingFromDAL = false;
    }

    static public void Add(ICustomer obj)
    {
        //add code to add
    }

    static public void Update(ICustomer obj)
    {
        //add code to update
    }
}



pelinville replied on Friday, May 26, 2006

Malloc
 
I get it!  I stared at the screen for at least thirty minutes before getting that eureeka moment.
 
This is what threw me...
 
//this property is acutally located in Business Base.
    bool ILoadFromDaL.LoadingFromDAL
    {
    get
    {
        return mLoadingFromDAL;
    }
    set
    {
        mLoadingFromDAL = value;
    }
    }
 
    public void Load()
    {
        CustomerDAL.Fetch(this)
    } 

Didn't under stand you Modified BusinessBase (or have a class that extends BusinessBase).  And that there is no factory methods. 
 
A part of me really likes this.  REALLY like it.
 
The only thing that I don't like is that my DAL has to be updated and wouldn't be able to work with the different versions of the apps which are accessing it. Sad [:(]
 
But i will have to remember this.  Thanks!

malloc1024 replied on Friday, May 26, 2006

Pelinville,

I didn’t have a lot of time to write up the puesdo-code at the time.  The code could have been clearer.  BusinessBase actually implements ILoadFromDAL and contains the IloadFromDal.LoadingFromDAL property.  The mLoadingFromDAL variable also resides in the BusinessBase.  Customer should have inherited from BusiessBase as well.  There is actually a lot more code to this that I didn’t add for the sake of brevity.  I will try to edit some of the code in that post to make it easier to understand.  Thanks for taking a look at it. 

malloc1024 replied on Saturday, May 27, 2006

If you want to load a collection of objects from the DAL you can use another interface for the collection.  This time the code is written in VB.NET

'//////////////////////////////////////////
'Intefaces located in Separate Assembly

Public Interface IAddress
    Property Foo () As String
End Interface

'The following interface is implemented in the collection
Public Interface IAddFromDAL
    Function AddFromDAL() As IAddress
End Interface

'//////////////////////////////////////////
'BusinessLayer

Public Class Address
    Inherits BusinessBase
    Implements IAddress

    Private mFoo As String

    Property Foo () As String Implements IAddress.Foo
        Get
            Return mFoo
        End Get

        Set(ByVal Value As String)
             mFoo = Value
             If NOT LoadingFromDAL
              //CheckRule, MarkDirty etc.

             END IF
        End Set
    End Property

End Class

Public Class Addresses
    Inherits BusinessCollectionBase
    Implements IAddFromDAL

     Public Sub Load() //Loads All of the address objects
       AddressDAL.Fetch(Me)
    End Sub

//This is called from the DAL. Note that it is private.  It can be called from the DAL
//because of the explict interface.  However it cannot be called from the UI.
Private Function AddFromDAL() As IAddress Implements IAddFromDAL.AddFromDAL
        Dim obj As New Address()
        list.Add(obj)
        Return obj
    End Function

End Class

'//////////////////////////////////////////
'DAL

Public Class AddressDAL
    Public Shared Sub Fetch(ByVal p As IAddFromDAL)
    Dim obj As IAddress
    For each record in recordset
        obj = p.AddFromDAL
        obj.LoadingFromDAL = True;
        obj.Foo = record["Foo"]
        obj.LoadingFromDAL = False;
    Next
End Sub

End Class

DavidDilworth replied on Tuesday, May 30, 2006

RockfordLhotka:
A DTO, or ORM, cause the same double-copy as with a DataSet.
Just a quick note on this point.  NHibernate loads the private member fields of the instance object directly from (I think) an NDataReader (i.e. an NHibernate DataReader).
 
Therefore, it's only doing a "single-copy".

RockfordLhotka replied on Thursday, May 25, 2006

No, of course not :)
 
I've been saying for some time now that the next big thing will be OMM (object message mapping). Similar to ORM, but mapping against SOA messages instead of relational tables.
 
Rocky


From: DavidDilworth [mailto:cslanet@lhotka.net]

 [...] For the DTO concept to work then the definition of the object should be driven by the XSD schema definition in the web service via the WSDL, which defines your contract with the outside world.

We're currently running a Web Service project using a technique called Web Services Contract First (WSCF).  This starts with the contract (i.e. interface) you agree with the outside world for your Web Service.  We've found that going down this route you then need facade classes to bridge between the class definitions used by the Web Service and those of your BO.  These are somewhat analagous to the "facade" classes in the ProjectTracker Web Services example, where the code maps the data between the BO class and Web Service class.  In our case, the two are not exactly 100% the same - things are never that easy  [...] 

Fabio replied on Friday, May 26, 2006

Hi David.
The followin text is part of "Hibernate in Action"
"The application might have multiple SessionFactorys if it accesses multiple datasources.
But you should never create a new SessionFactory just to service a particular
request—creation of a SessionFactory is extremely expensive. On the other
hand, Session creation is extremely inexpensive; the Session doesn’t even obtain a
JDBC Connection until a connection is required."
I have a different approach to use NHibernat with-in CSLA.
I had create a NHibernateHelper class with a singleton; it's responsability is:
mantein a sigle instance of NHibernate.Cfg.Configuration
Add assemblies to the configuration
create NHibernate.ISession
This class can work with or without CSLA.

In the same assembly i have another class PersistanceManager. It's responsability is to give me APIs to persist objects using NHibernate with the approach session-per-request.
An example of a method of PersistanceManager is:
        public static void Save(object obj)
        {
            ISession session = NHibernateHelper.Instance.GetSession();
            try
            {
                ITransaction transaction = session.BeginTransaction();
                session.Save(obj);
                try
                {transaction.Commit();}
                catch (NHibernate.HibernateException)
                {
                    transaction.Rollback();
                    throw;
                }
            }
            finally
            { session.Close(); }
        }
In the future, i can chage the approch without chage other classes but PersistanceManager.

To use this clases from CSLA i have create a new assembly named CslaNHb with an extention of BusinessBase
namespace CslaNHb
{
    [Serializable()]
    public abstract class BusinessBase<T> : Csla.BusinessBase<T> where T : BusinessBase<T>
......
In this class i have, for example
        protected override void DataPortal_Insert()
        {
            HibernateHelpers.PersistanceManager.Save(this);
        }

Looking inside this approch:
-If you hinerit from CslaNHb.BusinessBase you don't need to implement any data access method or, if you want, you can override all data access methods.
-In the future i can chage the ORM without change my BOs
-If Roky change the CSLA using some other ORM-FW i can change only the base class from my CslaNHb.BusinessBase to CsalXYZ.BusinessBase (really i hope this is the only chage i must do in my's BOs).
Now i'm studing how to use the potencial of Hibernate criteria class without using intrusive code in my BOs.

What happens if  "C# Business Objects 3 Edt" come with DLinq ?

Bye.
Fabio.

DavidDilworth replied on Friday, May 26, 2006

Although I don't have that specific book, the statement is actually obvious when you think about what is going on.

So we anticipated that and decided to use a singleton pattern.  Well actually a singleton HashTable of NHibernate.SessionFactory, as we are catering for multiple database usage.

So our line of code:

// Get an NHibernate session factory
 NH.ISessionFactory sessionFactory = Nfs.Nhibernate.Cfg.BuildSessionFactory(SessionFactoryKey);

doesn't create a new NHibernate.SessionFactory every time - only the first time a new SessionFactoryKey is requested.  After that, it's simply returning the pre-built SessionFactory from the singleton HashTable (this is all handled inside our wrapper code - notice the namespace).

We could have chosen to wrap that code further as well to make it ORM neutral, which is what you've chosen to do.  But we decided against that.

However, it's good to know that we're thinking along the same lines Smile [:)]

We have already used the criteria object so we are now writing code like this:

// Check MinCovers allowed is greater than requested
NH.Expression.GeExpression minExpression = new NH.Expression.GeExpression("MinCovers", _unavailableRoomListCriteria.NoOfCovers);

// Check MaxCovers allowed is not less than or equal to the amount requested
NH.Expression.LeExpression maxExpression = new NH.Expression.LeExpression("MaxCovers", _unavailableRoomListCriteria.NoOfCovers);

// Add the check as an "OR" constraint
nhibernateCriteria.Add(new NH.Expression.OrExpression(minExpression, maxExpression) );

 

willfarnaby replied on Thursday, June 15, 2006

David:

I've done a fair bit of Hibernate (v2, v3) work in Java, and am just about to look at NHibernate, to use with CSLA.

It appears to me in your code you're creating SessionFactory objects with abandon. AFAIK (i.e., in Hibernate) SessionFactory is extremely heavyweight. I've always created a SessionFactory singleton via dependency injection in the Spring Framework, in effect before the application proper even runs. The singleton is then used throughout the app to create lightweight Hibernate Session objects.


----------------------------------------------

As an example of what our BO code looks like, here is an extract from our abstract base class class called NhibernateReadOnlyBase.  This forms the basis for our ReadOnly BOs.  The only thing we have to do in our concrete BO class is mark the properties that are being persisted with an NHibernate specific attribute - NHibernate then takes care of the rest.

protected override void DataPortal_Fetch(object criteria)
{
 // Get an NHibernate session factory
 NH.ISessionFactory sessionFactory = Nfs.Nhibernate.Cfg.BuildSessionFactory(SessionFactoryKey);

 // Get an NHibernate session from the factory
 using (NH.ISession session = sessionFactory.OpenSession())
 {
  // Get the identifier required from the criteria
  object identifier = GetNhibernateIdentifier(criteria);

  // Load the current instance from the NHibernate session based on the identifier
  session.Load(this, identifier);
 }
}


willfarnaby replied on Thursday, June 15, 2006

Ah, I see this issue was discussed earlier in the thread (sans Spring Framework, which name reminds me of Spring.NET).

DavidDilworth replied on Monday, June 19, 2006

Will,

As you rightly pointed out I covered the fact that we do use a singleton pattern earlier in the thread.

Good to see someone with "real-world" Hibernate experience on the forums.

Welcome to the CSLA.NET world!

Copyright (c) Marimer LLC