How do I mark a BusinessBase object Added to BusinessListBase IsNew property = false?

How do I mark a BusinessBase object Added to BusinessListBase IsNew property = false?

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


BM2010 posted on Wednesday, August 26, 2009

I'm not sure if I am doing this correctly, but I created an editable BusinessBaseList object and populated the collection with BusinessBase objects loaded from a database and bound it to a grid. AddNew items were subsequently added to the list via the grid. When I attempt to update, I am using an override to Dataportal_Update() in the BusinessBaseList object that iterates over its collection and calls the BusinessBase.Save() method.

For some reason, it seems ALL objects in the collection are marked as IsNew = true... including the ones I loaded from the database. This is causing them to be Inserted again (with a new uniqueidentifier) rather than updated.

I am not sure I am doing this in the most appropriate way... and not sure how to have all objects in the list that were loaded from the database using an iteration of SafeDataReader to Add them to the list to be marked with IsNew = false.

FYI, The I am using the following code snippet in BusinessListBase:

private void DataPortal_Fetch(Criteria criteria)
{
// fetch with no filter
Fetch(criteria);
}

private void Fetch(Criteria criteria)
{
this.RaiseListChangedEvents = false;
using (SqlConnection cn = new SqlConnection(Database.CardConnection))
{
cn.Open();
using (SqlCommand cm = cn.CreateCommand())
{
if (criteria.Filter == string.Empty)
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "ge_Capture_List";
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
//IsReadOnly = false;
while (dr.Read())
{
this.Add(Capture.GetCapture(dr));
}
//IsReadOnly = true;
}
}
}
}
this.RaiseListChangedEvents = true;
}

rsbaker0 replied on Wednesday, August 26, 2009

I don't have my code in front of me, but I believe I'm calling "MarkOld" on object that I load in this manner.

JoeFallon1 replied on Wednesday, August 26, 2009

In my child BO I pass in the dr to Fetch the data and also call a few other methods as part of my standard coding practice. (PostFetchData and FetchChildren are usually empty Overridable Subs).

But then I always call MarkOld() and CheckRules. It is the call to MarkOld() which will cause you to do Updates later instead of Inserts.

Protected Overridable Sub Fetch(ByVal dr As SafeDataReader)
  SetDefaults()
  FetchData(dr)
  PostFetchData()
  FetchChildren()
  MarkOld()
  ValidationRules.CheckRules()
End Sub

JonnyBee replied on Thursday, August 27, 2009

Hi,

You are probable not receiving the new list returned after Save (with updated child objects).

See Joes reply in another thread:
http://forums.lhotka.net/forums/permalink/35798/35804/ShowThread.aspx#35804

/jonnybee

BM2010 replied on Thursday, August 27, 2009

The problem I am having is that the SafeDataReader is being executed in BusinessListBase, which does not have a MarkOld() method. (I copied this pattern from roles.cs in ProjectTrackercs).

Also, I am doing the following in BusinessListBase, which I am not sure is the right way to do this:

protected override void DataPortal_Update()
{
foreach (Capture capture in this)
{
if (capture.IsNew)
capture.Save();
}
}

JonnyBee replied on Thursday, August 27, 2009

Hi,

Which verion of Csla are you using?

In DataPortal_Update, DataPortal_Insert, Child_Insert or Child_Update you should call MarkOld on each object as it is saved. This will set IsNew to false.

/jonnybee

BM2010 replied on Thursday, August 27, 2009

I am using version 3.7.

The problem seems to be in copying the pattern Lhotka used in ProjectTracercs roles.cs. There is a SafeDataReader used in Fetch(Criteria) in a BusinessListBase where BusinessBase objects are Added to the collection in a foreach loop returned from a stored procedure call in the db using "this.Add(Capture.GetCapture(dr));". There is no MarkOld() method in this class... it only appears to be in the BusinessBase class, so all of the objects are defaulting to IsNew=true.

RedShiftZ replied on Thursday, August 27, 2009

BM2010:
I am using version 3.7. The problem seems to be in copying the pattern Lhotka used in ProjectTracercs roles.cs. There is a SafeDataReader used in Fetch(Criteria) in a BusinessListBase where BusinessBase objects are Added to the collection in a foreach loop returned from a stored procedure call in the db. There is no MarkOld() method in this class... it only appears to be in the BusinessBase class, so alll of the objects are defaulting to IsNew=true.


I think I see your dilemma, and here is how I do this...

DataPortal_Fetch for the List...
    private void DataPortal_Fetch(MyCriteria criteria)
    {
      using (var mgr = ConnectionManager<SqlConnection>.GetManager("MyDataBase"))
      {
        using (var cmd = mgr.Connection.CreateCommand())
        {
          cmd.CommandType = System.Data.CommandType.StoredProcedure;
          cmd.CommandText = "myList_Select";

          cmd.Parameters.AddWithValue("@Date", criteria.Date);

          using (var dr = new SafeDataReader(cmd.ExecuteReader()))
          {
            while (dr.Read())
            {
              MyItem mi = MyItem.GetItem(dr);
              this.Add(mi);
            }
          }
        }//using
      }//using
    }

And in the BB Factory Method...
    public static MyItem GetItem(SafeDataReader dr)
    {
      return new MyItem(dr);
    }

    private MyItem()
    { /* require use of factory method */ }

    internal MyItem(SafeDataReader dr)
    {
      LoadData(dr);
    }
    private void LoadData(SafeDataReader dr)
    {
      LoadProperty(ItemIDProperty, dr.GetInt32("ItemID"));
      _tStamp = (byte[])dr.GetValue("TStamp");

      MarkOld();
    }


So MarkOld is called on the BB itself.


RedShiftZ replied on Thursday, August 27, 2009

BM2010:
The problem I am having is that the SafeDataReader is being executed in BusinessListBase, which does not have a MarkOld() method. (I copied this pattern from roles.cs in ProjectTrackercs). Also, I am doing the following in BusinessListBase, which I am not sure is the right way to do this: protected override void DataPortal_Update() { foreach (Capture capture in this) { if (capture.IsNew) capture.Save(); } }


The correct call for this "capture.Save();" is "capture = capture.Save();" but that will not work in a foreach loop as you cannot reassign the variable inside the loop.

Based on your using Roles as a roadmap, your DataPortal_Update should be calling Child_Update(); or FieldManager.UpdateChildren(this);

This will iterate through all the children calling Save on those that need it.








JonnyBee replied on Thursday, August 27, 2009

Hi Jeff,

No, inside the DataPortal_Update on your list - the save of each child does no return a new object.

But in your Form you must have code like:
    myList = myList.Save();

The Save method on a Root object will return a new instance of you Root.

/jonnybee

RedShiftZ replied on Friday, August 28, 2009

JonnyBee:
Hi Jeff,

No, inside the DataPortal_Update on your list - the save of each child does no return a new object.

But in your Form you must have code like:
    myList = myList.Save();

The Save method on a Root object will return a new instance of you Root.

/jonnybee


Hey Jonny,
  No I wasn't trying to state that his DataPortal_Update was right, just that that particular line was incorrect syntax. And I apparently misread which unit it was because for some reason I was thinking we were discussing this in terms of a BB with children. That's what I get for trying to respond to multiple things at the same time I suppose. :)

Thanks for the save,

Jeff

Copyright (c) Marimer LLC