Stack overflow error when override IsValid

Stack overflow error when override IsValid

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


Zafar Ullah posted on Wednesday, July 02, 2008

Hello

I am facing a stack overflow exception when ever i override  

public override bool IsValid

{

get { return base.IsValid && this.IsValid; }

}

this piece of code in my business object. System keep on calling this code and finally throw exception.

I have tried this with CSLA 3.0.3.0 & CSLA 3.0.4.0 version and the problem still exists. Please help stuck badly.Sad [:(]

Regards

Zafar Ullah

skagen00 replied on Wednesday, July 02, 2008

What are you trying to accomplish? You're getting recursion because IsValid is essentially calling itself (when you say this.IsValid). Hence your never ending loop.

If you just have a root object with no children, you shouldn't normally override IsValid unless you have other circumstances. The base class behavior is sufficient.

JoeFallon1 replied on Wednesday, July 02, 2008

I agree that this.IsValid is the source of the Stack overflow.

I sometimes override IsValid to call specific cases of CheckRules and once the rules have been run then I call into base.IsValid to see if any rules are broken.

In 3.5 the framework should take care of IsValid for the root BO and all of its children. So there is even less of a reason to override it than in previous versions.

Joe

 

Zafar Ullah replied on Thursday, July 03, 2008

Thanks joe for a quick reply

You have mention that 3.5 framework will take care of IsValid for the root BO and its childrens. Can you or any body tell how to handle this in 3.0.4.0 version of CSLA. I cant use 3.5 because my web application is not using any feature of 3.5 framework so no need to have that.

Basically i am checking it because of custom rules implementation.

Or what u say if i check that manually by making changes in given below method which i call in Add Custom rules method.

ValidationRules.AddRule<AMEmp>(UniqueName, "Name");

private static bool UniqueName(AMEmp target, Csla.Validation.RuleArgs e)

{

    int result = AMNameList.GetList().Key(target._name+target.number);

      if(result != 0)

    {

              e.Description = "Name must be unique";

             return false;

     }

    else

    {

       return true;

     }

}

Thanks

JoeFallon1 replied on Thursday, July 03, 2008

In earlier versions of CSLA you have to override IsValid to call down into any contained child objects. Same for IsDirty.

I wrote code to do this call recursively in my own framework. Rocky has now implemented the same concept in 3.5 so developers no longer have to do this. Other posts (from me and others) have some sample code for how to do this. You can look for thme if you really want to know how to do it.

Also, I am not sure why you are having an issue with the rule. It is attached to a real property and that property changes so the rule should run during the property set in that case. No need to override IsValid just to call that rule.

What I am talking about is the case where a rule needs to be run *after* all properties have been set. Then you can override IsValid, run the extra rule and then call MyBase.IsValid.

An example is the case where you have 5 checkboxes on a form and 1 of them *must* be checked. Rather than write the rule and have it run 5 times - you write it once and call it after all properties are set.

Joe

 

Zafar Ullah replied on Thursday, July 03, 2008

Joe you are absolutly write that the rule should run during the property set  and thats how it does and return false to the caller. Now when the run time environment reach Save() and if i check the IsValid property of the current object then its * true * where as it should be * false* because the rule returns false.

Now during debugging i check base object and its IsValid property is false.

So as the Broken rule collection is beign accesed from the base class that is why i am checking this. 

I have 2 options now

1.   To check the uniqueness of the columns manually (i.e by calling UniqueName method mentioned in earlier post) just before save and comment out overriden IsValid property.

2. Or what if before save i just check the broken rule collection and throw ValidationException if collectioncount > 0 .

Which option is better. also will you please give a link of other post you are talking about.

Thanks

ajj3085 replied on Monday, July 07, 2008

Is the broken rule in the root object or on one of the child objects?  If it's on the child, you need to do something like this:

public override bool IsValid {
  get  { return base.IsValid && child.IsValid; }
}

Andy

Zafar Ullah replied on Tuesday, July 08, 2008

Thanks Andy,

but if you see my first post thats exectly as u have written and actully its the issue.

I go for the second option i.e i check broken rules collection just before saving my BO and if its count is greater then 0 i just throw exception. here i go...

if (obj.BrokenRulesCollection.Count > 0)

throw new Csla.Validation.ValidationException();

obj = obj.Save();

rowsAffected = 1;

}

catch (Csla.Validation.ValidationException ex)

{

System.Text.StringBuilder message = new System.Text.StringBuilder();

//message.AppendFormat("{0}.\\n\\n", ex.Message);

if (objWell.BrokenRulesCollection.Count == 1)

message.AppendFormat("* {0}: {1}.",

objWell.BrokenRulesCollection[0].Property,

objWell.BrokenRulesCollection[0].Description);

else

foreach (Csla.Validation.BrokenRule rule in objWell.BrokenRulesCollection)

message.AppendFormat("* {0}: {1}.\\n ", rule.Property, rule.Description);

WebMsgBox.Show(message.ToString());

rowsAffected = 0;

}

catch (Csla.DataPortalException ex)

{

WebMsgBox.Show(ex.BusinessException.Message);

rowsAffected = 0;

}

catch (Exception ex)

{

WebMsgBox.Show(ex.Message);

rowsAffected = 0;

}

 

 

ajj3085 replied on Tuesday, July 08, 2008

No, what I wrote and what you wrote are NOT the same...

You had:
public override bool IsValid {
   get { return base.IsValid && this.IsValid; }
}

where-as I wrote:
public override bool IsValid {
   get { return base.IsValid && child.IsValid; }
}

Where child is either a subclass of BusinessListBase or BusinessBase, depending on what your design was.

HTH
Andy

Dawn replied on Tuesday, July 08, 2008

I guess your want to validate aganist Root BO name uniqueness, nothing about child collection.  So you need not override IsValid, just add the validation rule will be ok.
But add this validation rule will not  promise the name uniqueness aganist database in multiuser environment, I think the best way is in you DataPortal_Update() method, begin a transaction, then check if there exists same name in database, if exists throw a exception.

Copyright (c) Marimer LLC