CSLA .NET 3.5 enhancement - child persistance

CSLA .NET 3.5 enhancement - child persistance

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


RockfordLhotka posted on Friday, January 04, 2008

I just posted a new preview version of 3.5 for download. The VB code includes a new concept around simplifying how child objects are persisted - create/fetch/insert/update/delete. The goal is to save code in root objects and list objects, and to standardize the coding model for all objects.

The code in the download is not completely tested, but basic tests all pass and so I think it is worth putting out for people to kick the tires. Regardless of whether you use C# or VB, if you get a chance to build some business classes against the VB framework your feedback would be invaluable!

I want to be very clear that this is all entirely optional. If you don't like it (because it does use reflection just like the data portal always has) then you can continue to use the model from 3.0 and earlier. Nothing compels you to use this new model (except for radical simplification of code Wink [;)]), and if you don't use it then you incur no extra overhead or cost.

The new child object pattern is this:

[Serializable]
public class Child : BusinessBase<Child>
{
  internal static Child NewChild()
  {
    return DataPortal.CreateChild<Child>();
  }

  internal static Child GetChild()
  {
    return DataPortal.FetchChild<Child>();
  }

  private Child()
  {
    MarkAsChild();
  }

  private void Child_Create()
  {
    // initialize new child here
  }

  private void Child_Fetch()
  {
    // load child data here
  }

  private void Child_Insert()
  {
    // insert child data here
  }

  private void Child_Update()
  {
    // update child data here
  }

  private void Child_DeleteSelf()
  {
    // delete child data here
  }
}

Please note that no calls to MarkNew() or MarkOld() are required, they are all handled by the data portal just like they are for root objects.

The new editable root (parent) pattern is this:

[Serializable]
public class RootParent : BusinessBase<RootParent>
{
  // other class code here ...

  protected override void DataPortal_Insert()
  {
    using (SqlConnection cn = new SqlConnection(...))
    {
      // insert parent data here

      FieldManager.UpdateChildren();
    }
  }

  protected override void DataPortal_Update()
  {
    using (SqlConnection cn = new SqlConnection(...))
    {
      // update parent data here

      FieldManager.UpdateChildren();
    }
  }
}

The call to UpdateChildren() automatically cascades appropriate insert/update/delete calls to all child objects (including collections).

The new editable root list pattern is this:

[Serializable]
public class ChildList : BusinessListBase<ChildList, Child>
{
  // other class code here ...

  protected override void DataPortal_Update()
  {
    using (SqlConnection cn = new SqlConnection(...))
    {
      Child_Update();
    }
  }
}

The only reason you still need to override DP_Update() is so you can manage the connection details (or LINQ context, or whatever).

The new editable child list pattern is this:

[Serializable]
public class ChildList : BusinessListBase<ChildList, Child>
{
  internal ChildList()
  {
    MarkAsChild();
  }

  // other class code here ...
}

Notice that there is no data access code here, because child updates are now handled entirely by the base class.

bmmathe replied on Friday, April 18, 2008

Rocky,

I noticed in ProjectResources you are passing in an array of Assignment to populate the ProjectResource list.  The GetProjectResources method is executed in the DataPortal_FetchChild method of Project.  The ProjectResources static factory Get method then calls return DataPortal.FetchChild... which in turn calls Child_Fetch...  GetProjectResource which is called in ProjectResources.DataProtal_ChildFetch also uses the same DataPortal.FetchChild pattern.

The question is, why do we keep going back to the DataPortal when we are already in the data portal context?  How come you don't call use the "deep data" pattern where the child collection and child are populated by passing the data (reader) into the constructor?

 

 

RockfordLhotka replied on Wednesday, April 23, 2008

One major enhancement in CSLA 3.5 is that the data portal now supports the concept of child objects.

 

Notice that the call is to FetchChild(), not Fetch(). The data portal includes special treatment of child objects – very lightweight, but with the same coding structure as a root object.

 

One of the biggest training issues with CSLA has always been that root objects and child objects are coded differently. The very structure of the code (which methods you write and how they are called) are different.

 

The new child support in the data portal means that the coding structure for a root and child are the same. The method names are slightly different – Child_XYZ instead of DataPortal_XYZ – but that’s good (imo) because it clarifies whether the object is a root or child. But the structure is the same, so every object has the same “look and feel”.

 

If you don’t like the new model, and prefer the old 1.0-3.0 coding style, you are free to use that approach. Nothing in 3.5 blocks you from using the older coding technique.

 

But I like the new approach because the code is much more consistent across all the objects – making training easier, and even simplifying code-gen or the use of snippets.

 

Rocky

Philip replied on Wednesday, April 23, 2008

I agree with Rocky. It is one of the issues when I was trying to code the Code Complete templates. I am sure it will simplify my job dramatically and it comes on time as I am in the process of re-writing the templates for version 3.5 and LINQ.

Thanks

Philip

selim51 replied on Monday, May 05, 2008

Hi Rocky!

Is there really a need for calling MarkAsChild() in the constructor of the child? I don't call MarkAsChild(), it is called automatically by DataPortal.CreateChild<Child> and DataPortal.FetchChild<Child> like MarkOld() and MarkNew().

Yavuz

RockfordLhotka replied on Monday, May 05, 2008

No, in the release bits for 3.5 if you use the new child data portal features you do not need to manually call MarkAsChild.

Rocky (sent from my phone)

-----Original Message-----
From: "selim51"
To: "rocky@lhotka.net"
Sent: 5/5/2008 2:23 PM
Subject: Re: [CSLA .NET] CSLA .NET 3.5 enhancement - child persistance

Hi Rocky!

Is there really a need for calling MarkAsChild() in the constructor of the child? I don't call MarkAsChild(), it is called automatically by DataPortalCreateChild and DataPortal.FetchChild like MarkOld() and MarkNew().

Yavuz

rsargent replied on Friday, August 22, 2008

If my child object contains children do I need to change the Child_Insert and Child_Update methods to look like the following:

  private void Child_Insert()
  {
    // insert child data here
      FieldManager.UpdateChildren();

  }

  private void Child_Update()
  {
    // update child data here
      FieldManager.UpdateChildren();

  }

Is there a reason the DataPortal objects do not call FieldManager.UpdateChildren() in the Update method?

ajj3085 replied on Friday, August 22, 2008

I haven't had a lot of experience with Managed properties yet, but I haven't found a need to use FieldManager at all.  All I do in my Child_Update / Insert is the data access code.. if the child has children, then I call DataPortal.UpdateChild.  For example:

                DataPortal.UpdateChild(
                    ReadProperty( SerialNumbersProperty ),
                    item
                );

Where SerialNumbersProperty is a BusinessListBase subclass property.

RockfordLhotka replied on Friday, August 22, 2008

If you have more than one child, or just want to simplify your code, you can just call

 

FieldManager.UpdateChildren()

 

And let the field manager do the work for you.

 

Rocky

 

From: ajj3085 [mailto:cslanet@lhotka.net]
Sent: Friday, August 22, 2008 8:12 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] CSLA .NET 3.5 enhancement - child persistance

 

I haven't had a lot of experience with Managed properties yet, but I haven't found a need to use FieldManager at all.  All I do in my Child_Update / Insert is the data access code.. if the child has children, then I call DataPortal.UpdateChild.  For example:

                DataPortal.UpdateChild(
                    ReadProperty( SerialNumbersProperty ),
                    item
                );

Where SerialNumbersProperty is a BusinessListBase subclass property.


ajj3085 replied on Friday, August 22, 2008

Thanks for the tip... is the book still on schedule?  Smile [:)]  Amazon lists 9/5/2008 as the ship date.

RockfordLhotka replied on Monday, August 25, 2008

The book is on a “revised” schedule, which is to say we’re shooting for a December release – which is putting a strain on everyone (me, publisher, reviewers) but we’re working toward that end.

 

Rocky

 

From: ajj3085 [mailto:cslanet@lhotka.net]
Sent: Friday, August 22, 2008 11:46 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: CSLA .NET 3.5 enhancement - child persistance

 

Thanks for the tip... is the book still on schedule?  Image removed by sender. Smile <img src=">  Amazon lists 9/5/2008 as the ship date.


RockfordLhotka replied on Friday, August 22, 2008

That’s a good question – worth considering!!

 

Rocky

 

 

From: rsargent [mailto:cslanet@lhotka.net]
Sent: Friday, August 22, 2008 7:09 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] CSLA .NET 3.5 enhancement - child persistance

 

If my child object contains children do I need to change the Child_Insert and Child_Update methods to look like the following:

  private void Child_Insert()
  {
    // insert child data here
      FieldManager.UpdateChildren();

  }

  private void Child_Update()
  {
    // update child data here
      FieldManager.UpdateChildren();

  }

Is there a reason the DataPortal objects do not call FieldManager.UpdateChildren() in the Update method?


Copyright (c) Marimer LLC