Changes in SetNewFieldValue behavior

Posts   
 
    
alex
User
Posts: 68
Joined: 30-Mar-2004
# Posted on: 20-Jul-2005 15:58:02   

Hi,

I installed 1.0.2004.2 upgrade and ran the NUnit tests on my business classes. I've noticed that SetNewFieldValue method works differently now. If you trying to set a null value in the field, the method works only if the database column that the field is mapped to allows nulls. That's not how this method worked in the previous version.

Could you tell me why the behavior of the method was modified and is it possible to reverse the change, because there are multiple places in our app that are broken now.

Thanks a lot,

Alex

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jul-2005 16:51:17   

This is done to prevent a query which fails because of the null value, which is often a problem, as it results in a runtime exception.

By not setting the null value if the field is not allowed to have nulls, no exception is given, the field is not set, that's all. Which was the behavior of selfservicing, and adapter, which previously didn't have this information in the entity fields, now has the same behavior.

If your app is now broken, it was already broken, as you would save a null value in a field which isn't nullable, which would result in a runtime exception in any case. At least, that's how I see it. If I miss something, or if you have any more information about your situation, please let me know.

Frans Bouma | Lead developer LLBLGen Pro
alex
User
Posts: 68
Joined: 30-Mar-2004
# Posted on: 20-Jul-2005 17:15:06   

We have validation methods in our business classes that throw an exception if the required (not nullable) fields do not have values in it. This validation is fired when the user clicks the "Save" button.

That's how our application works: We have a web form that retrieves and updates information about an animal (for example). The user can modify this information and click the "Save" button. At this time we collect data from all the form fields by setting the properties in the Animal object. Then we pass this object to our SaveEntity service that performs all validations and persists the object in the database. Now, if the user clears the value from the required field (for some reason), we need to set the null value in the corresponding Animal object property. Later, the SaveEntity serivce will catch that the property has a null value where it's not supposed to and throw an exception that will result in the "Required field missing" error message displayed to the user.

Since SetNewFieldValue method has a different behavior now, the following will happen in our application: The user clears the value from the required field and clicks the "Save" button. The "Required field missing" message will not be displayed and it will look like the user saved the animal information with no data in the required field. But later, after re-retrieve, the data that the user got cleared will come back, because SetNewFieldValue(null) method failed and the object property value was not actually set to null.

Sorry for such a long explanation, but that's a problem that we're going to have now.

Thanks, Alex

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jul-2005 18:53:17   

Ok, I see your problem regarding your current situation. The core cause IMHO is in the webform data which ignores the return value of SetNewFieldValue. If the code had tested on the return value, it would have known the value wasn't set, which then could have been handled by the webform itself, for example by showing a validator on the form. As this is a nullable related situation, it is not depending on some rule which field is mandatory or not, it has to get a value otherwise the save fails. The entity has to make sure data inside itself is correct. That's the reason why it rejects the value, as it's not correct: the field is not nullable for the entity.

You can check on the client (in the webform) if a field is nullable or not: entity.Fields[index].IsNullable You can use that to decide which fields are mandatory or not, on your webform and use asp.net validators to test for correctly filled in data.

I know this is not the answer you want to hear, but it's the correct way of how an entity should behave, IMHO: if a value is accepted in the situation in which the entity knows it's not correct, it's not OK.

Frans Bouma | Lead developer LLBLGen Pro
alex
User
Posts: 68
Joined: 30-Mar-2004
# Posted on: 20-Jul-2005 20:52:08   

Our original intent was to have all validation including checking for required fields in the business objects (server side). We didn't want to use client side validation.

Since it's not going to work any more, we'll have to think about changing design, unless you could reverse this particular change to the SetNewFieldValue method.

I understand that the reason why you chaged behavior of this method was to avoid runtime exceptions if the developer sets a null value in the field that is mapped to the database column that does not allow nulls. But if the developer does this by mistake, the runtime exception is appropriate, so the developer can correct his or her code. If the developer does something like this intentionally (like in my case), let them handle this situation. I think, the purpose of the SetNewFieldValue method is to set the value that is passed to it, so let it do it!

Did you change this method because someone reported a defect?

Thanks,

Alex

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jul-2005 21:42:02   

alex wrote:

Our original intent was to have all validation including checking for required fields in the business objects (server side). We didn't want to use client side validation.

Since it's not going to work any more, we'll have to think about changing design, unless you could reverse this particular change to the SetNewFieldValue method.

No, I won't reverse this, sorry. Selfservicing already tested on this since the beginning, as the nullability of a column was available. In Adapter this wasn't the case until 1.0.2004.2, it always accepted null values while it wasn't correct.

Entities for example also check for lengths of binary values and strings. if you pass in a 100 char string to a field which has a length of 10, the value won't be set either.

I understand that the reason why you chaged behavior of this method was to avoid runtime exceptions if the developer sets a null value in the field that is mapped to the database column that does not allow nulls. But if the developer does this by mistake, the runtime exception is appropriate, so the developer can correct his or her code. If the developer does something like this intentionally (like in my case), let them handle this situation. I think, the purpose of the SetNewFieldValue method is to set the value that is passed to it, so let it do it!

If you want to bypass value checking, you should use: entity.Fields[index].CurrentValue = value; Be sure to set entity.Fields.IsDirty to true as well.

Did you change this method because someone reported a defect?

Yes, and because it was logical to do so, the behavior was changed.

I'm very sorry you ended up in this situation. It's often the case we have to make a choice between a rock and a hard place, as one customer reports an error so he can't continue, but by changing it other people run into problems and can't continue... This change is made over a version change, so it could be expected.

I have to admit, I didn't foresee your situation and the downside of having this. From the beginning the phylosophy was that error-preventing checks were done in the entity, by the entity, rule validation was done outside the entity, by plugged in objects (so executed in the entity, by the entity, but not part of the entity's core code).

Frans Bouma | Lead developer LLBLGen Pro
alex
User
Posts: 68
Joined: 30-Mar-2004
# Posted on: 20-Jul-2005 22:04:26   

Thank you, Otis.

I understand completely that there is no way you can satisfy all clients. We have exactly the same problem with our apps.

I've already tried to use the CurrentValue property and I think this will work for us. So, we'll be OK simple_smile

Thanks again for your great product and support!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jul-2005 22:19:11   

smile Glad there is a way you can move forward with this issue, Alex! simple_smile

Frans Bouma | Lead developer LLBLGen Pro