This is a bug?

This is a bug?

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


phucphlq posted on Monday, June 19, 2006

Hi!

I have a problem, it crash my project at runtime.

I have Employee BO(Employee is only an example, my project has many complex class)

 

[Serializable()]

public class Employee:Csla.BusinessBase<Employee>

{

      private string _Name;

      private Employee _Manager;

            // All properties and mothod is OK

}

 

My data: Employee_A{“Ronaldinho”, Employee_B)

         Employee_B(“Ronaldo”, Employee_C)

         Employee_C(“Calos”, Employee_A)

 

When edit an employee, stack will overflow in UndoableBase class, at following code:

 

// When field name is _Manager

object value = field.GetValue(this);

 

if (typeof(Csla.Core.IUndoableObject).IsAssignableFrom(field.FieldType))

{

// make sure the variable has a value

      if (value == null)

{

            // variable has no value - store that fact

            state.Add(GetFieldName(field), null);

      }

      else

      {

            // this is a child object, cascade the call

            ((Core.IUndoableObject)value).CopyState();  

            // This command is called much time until program is cracked

      }

}

miroslav replied on Tuesday, June 20, 2006

You have a circular reference between the Employee_A and the Employee_C.
The Employee_A contains reference to the Employee_B, which contains reference to the Employee_C, which contains reference to the Employee_A.

When you (or Windows Forms binding) call Employee.BeginEdit(), UndoableBase will try to serialize entire Employee's object graph. If the Employee contains other IUndoableObject objects (Manager), the call is cascaded to that object. The call will eventualy be cascaded back to the starting object, because of the circular reference. The whole thing will start all over again and repeat until the stack is full. StackOverflow!!!

You should probeably review your use cases first. Should this be allowed? If Ronaldinho is Ronaldo's manager and Ronaldo is Carlos' manager, can Carlos be Ronaldinho's manager?

If this kind of relations is allowed in your use cases, then you need to implement the Employee class differently.
You can mark the _Manager field with [NotUndoable] attribute, and add another field, i.e.: _ManagerName of type string. This way, the _Manager field will not participate in Undo operations, but the _ManagerName will. The _ManagerName will be saved as the part of Employee object's state. Now you need to override the UndoChangesComplete() method and to get back the reference to the _Manager object using the _ManagerName field.

Hope this helps.
Miroslav

Copyright (c) Marimer LLC