CLSA 3.8.4 - Child Save is not marked as Saved e.g. ISNew remaining True even after database save

CLSA 3.8.4 - Child Save is not marked as Saved e.g. ISNew remaining True even after database save

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


astellakis posted on Wednesday, May 30, 2012

I've recently moved across to the latest version of Code Smith (from v5)

I'm using the most recent CSLA templates (from Blake http://code.google.com/p/codesmith/ 3.1.zip)

We're testing some new developments (vb.net/SQL Server 2008)  and I have the following object

Currency (Editable Root)

CurrencyList (Editable Root List)

ExchangeRate (Editable Child)

ExchangeRates (Editible Child List)

Each currency has a ExchangeRates child object, detailing the exchange rates for that Currency.

the issue is that when editing the parent Currency object, it is correctly writing the child data to the database however it is not retaining the Exchange Rate ID assigned to it from the database.

 

I have put a watch on the child object and the child is getting updated with a new ID from the Database and the IsNew is set to False - all OK so far.

However the moment the process returns back to the ExchangeRates list e.g. Next Exchange Rate when inspecting the previous Exchange Rate (that we'd seen saved) the ID is 0 and IsNew = True

The cosequence is that we are now getting duplicate child entries being written when they are clearly being saved (again) each time the Save method is called.

So in a nut-shell ;

 

1. Parent and Child updates are being saved, so if I reload all the objects and just do updates then it's fine.

2. new Child additions are being saved but the object marked as dirty and IsNew=True even though save is working, so when the user saves again, the child gets re-inserted thus creating duplcates.

Not that this is very helpful, but the last time I was doing this sort of parent/child update was last year (version 5 of Codesmith) and it worked without a problem

Not sure if the recent template changes have mucked something up or if there is a bug in the build of CSLA

 

Any ideas?

thanks
Andrew

 

JonnyBee replied on Wednesday, May 30, 2012

Remember that Save actually returns a new Object, so your code should look like.

      bo = bo.Save();

The new object has updated status (IsNew = false) etc.

astellakis replied on Wednesday, May 30, 2012

Hi JonnyBee

you're right in as much as for a ROOT object it'll expect a

bo=bo.save,

which again on the face of it works.  However a Child can only seem to be updated through the

 For Each child As cExchangeRate In Me
            If child.IsDirty Then
                child.Insert(cn, parent)
            Else
                child.Update(cn, parent)
                '  child = child.Save
            End If
        Next

 

the issue is that the CHILD objects are not getting marked as saved (IsDirty=False, IsNew=False) and the ID field is not retained either (the one the Database IS assigning)

If I didn't know better it's almost doing a

1.   Dim tempExRate as ExchangeRate = (Child)Exchange Rate.CLONE

2.   (Child) Exchange Rate.Save

3.. Return tempExRate - so It returns an object that appears as per the original but without the save flag or values

Any other ideas?

thanks

 

Andrew

JonnyBee replied on Wednesday, May 30, 2012

I assume that you are using DataPortal_XYZ for Data Access.

You then have support methods in DataPortal as:

FieldManager.UpdateChildren(parent)  - will call Child_Insert/Child_Delete/Child_Update for all child objects in "parent" or

DataPortal.UpdateChild(child)  - will call Child_Insert/Child_Delete/Child_Update for all child objects in the "child" list.

These support methods will also call MarkOld to update state automatically.

Semantically the code is like:

BusinessListBase:

    protected virtual void Child_Update(params object[] parameters)
    {
      var oldRLCE = this.RaiseListChangedEvents;
      this.RaiseListChangedEvents = false;
      try
      {
        foreach (var child in DeletedList)
          DataPortal.UpdateChild(child, parameters);
        DeletedList.Clear();

        foreach (var child in this)
          if (child.IsDirty) DataPortal.UpdateChild(child, parameters);
      }
      finally
      {
        this.RaiseListChangedEvents = oldRLCE;
      }
    }

and in Csla.Server.ChildDataPortal.Update:

.......

          if (busObj.IsDeleted)
          {
            if (!busObj.IsNew)
            {
              // tell the object to delete itself
              lb.CallMethod("Child_DeleteSelf", parameters);
            }
            if (target != null)
              target.MarkNew();
            else
              lb.CallMethodIfImplemented("MarkNew");

          }
          else
          {
            if (busObj.IsNew)
            {
              // tell the object to insert itself
              lb.CallMethod("Child_Insert", parameters);

            }
            else
            {
              // tell the object to update itself
              lb.CallMethod("Child_Update", parameters);
            }
            if (target != null)
              target.MarkOld();
            else
              lb.CallMethodIfImplemented("MarkOld");
          }

        }
        else if (obj is CommandBase)
        {
          // tell the object to update itself
          lb.CallMethod("Child_Execute", parameters);
          operation = DataPortalOperations.Execute;

        }
        else
        {
          // this is an updatable collection or some other
          // non-BusinessBase type of object
          // tell the object to update itself
          lb.CallMethod("Child_Update", parameters);
          if (target != null)
            target.MarkOld();
          else
            lb.CallMethodIfImplemented("MarkOld");
        }

 

 

 

astellakis replied on Thursday, May 31, 2012

Unless I am missing something I never have used a explicit layer

 

perhaps this is a  (my) hang-up from previous versions but I have not used anything other than the methods available to the object

 

e.g. Save - on a Root object and

 for each child

 If child.isdirty then

  if child.isnew then

    child.insert(SQLConnection, parent)

        else

     child.update (SQLCOnnection, parent)

endif

 

 next

As I said before this has always worked in the past. so something has changed as the child objects are no longer getting updated as saved/clean

 

Any other ideas, or do I need to scrap it and find a previous version of Codesmith and associated templates as this is the only thing I've changes, as well as the version of the CSLA dll of course

 

thanks


A

omar.ouhlous replied on Friday, October 12, 2012

I came accross the same probleem:

var queue = MyQueue.NewMyQueue();

queue.Aanmaakdatum =

 

SmartDate.Now;

queue.ClientNumber =

 

"123456789";

 

 

 

var item = queue.AddNewMyQueueItem();

queue = queue.Save();

I see now that child object item is new and that the id has not been set. Ay suggestions? This probleem doesn't occure in CSLA version 2.1.

Copyright (c) Marimer LLC