Field doesn't get saved if set to default value

Posts   
 
    
ww
User
Posts: 83
Joined: 01-Oct-2004
# Posted on: 20-Oct-2004 21:52:31   

I have an entity class A with an Integer property SomeProperty.

If I create a new A and set SomeProperty to 0 (A.SomeProperty=0), SomeProperty doesn't get marked as changed, so it doesn't get saved to the database.

I assume that SetNewFieldValue just compares the new value to the current value when deciding whether to update the field. If the db value is Null, though, the current value has been defaulted to 0, which doesn't reflect the underlying database value.

Seems like SetNewFieldValue needs to look at whether the database value is null and not just compare current value to new value.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 21-Oct-2004 10:10:41   

This is a bug. I'll try to fix it. It indeed doesn't do a good job in testing all scenario's. It tests for currentvalue==null which is, when I again look at it, pretty bogus, it should be DbValue==null. But there are other scenario's as well which aren't covered I think. I'll re-check the list of scenario's and re-implement the check.

Expect a fix today.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 21-Oct-2004 11:28:21   

A fix for this is now available in the form of an update to the hotfix for the runtime libraries 1.0.2004.1. The hotfix will be rolled into the installer at the end of the day.

Frans Bouma | Lead developer LLBLGen Pro
Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 21-Oct-2004 11:39:56   

Hi Otis Is it the same bug as the unit test below show ?

            Employee emp = new Employee(13);
            this.MyContextOnHRANEW_NUNITTEST.Adapter.FetchEntity(emp);

            emp.SetNewFieldValue("EName", null);                // string
            emp.SetNewFieldValue("TlId", null);                 // int
            emp.SetNewFieldValue("ELastModification", null);    // DateTime
            emp.SetNewFieldValue("EBirthdate", null);           // DateTime
            
//          Assert.IsTrue(emp.Fields["EName"].IsNull);
//          Assert.IsTrue(emp.Fields["TlId"].IsNull);
//          Assert.IsTrue(emp.Fields["ELastModification"].IsNull);
            
            Assert.IsTrue(emp.Fields["EName"].IsChanged);
            Assert.IsTrue(emp.Fields["TlId"].IsChanged);
            Assert.IsTrue(emp.Fields["ELastModification"].IsChanged);
            
            Assert.IsNull(emp.Fields["EName"].CurrentValue);
            Assert.IsNull(emp.Fields["TlId"].CurrentValue);
            Assert.IsNull(emp.Fields["ELastModification"].CurrentValue);
            Assert.IsNull(emp.Fields["EBirthdate"].CurrentValue);

As you can see, I've put in comment the IsNull because it always return false event after a SetNewFieldValue (... , null). After this SetNewFieldValue, I expected to have an exception when trying to access to the fields, but I got the old value. When saving in database, I think (but I'm not sure) it save the OLD value.

I't the same bug ? thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 21-Oct-2004 11:51:17   

Fabrice wrote:

Hi Otis Is it the same bug as the unit test below show ?

            Employee emp = new Employee(13);
            this.MyContextOnHRANEW_NUNITTEST.Adapter.FetchEntity(emp);

            emp.SetNewFieldValue("EName", null);                // string
            emp.SetNewFieldValue("TlId", null);                 // int
            emp.SetNewFieldValue("ELastModification", null);    // DateTime
            emp.SetNewFieldValue("EBirthdate", null);           // DateTime
            
//          Assert.IsTrue(emp.Fields["EName"].IsNull);
//          Assert.IsTrue(emp.Fields["TlId"].IsNull);
//          Assert.IsTrue(emp.Fields["ELastModification"].IsNull);
            
            Assert.IsTrue(emp.Fields["EName"].IsChanged);
            Assert.IsTrue(emp.Fields["TlId"].IsChanged);
            Assert.IsTrue(emp.Fields["ELastModification"].IsChanged);
            
            Assert.IsNull(emp.Fields["EName"].CurrentValue);
            Assert.IsNull(emp.Fields["TlId"].CurrentValue);
            Assert.IsNull(emp.Fields["ELastModification"].CurrentValue);
            Assert.IsNull(emp.Fields["EBirthdate"].CurrentValue);

As you can see, I've put in comment the IsNull because it always return false event after a SetNewFieldValue (... , null).

IsNull returns true if the READ value from the database was NULL. So setting the field's value to null doesn't return true for IsNull then.

After this SetNewFieldValue, I expected to have an exception when trying to access to the fields, but I got the old value. When saving in database, I think (but I'm not sure) it save the OLD value. I't the same bug ? thanks

I'm not sure where you expect the exception, as this test should pass.

The bug fixed is when you have an integer field Foo (for example) in the database which is NULL, it gets the value 0 in the entity. Setting it to 0 would then not change the field (value is the same, but IsChanged flag should be set) and thus would not save Foo's new value 0 into the database.

Frans Bouma | Lead developer LLBLGen Pro
Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 21-Oct-2004 12:05:59   

I try to access the field below the code I've put (I've not put all code) When I make SetNewFieldValue and then I try to access to the fiels, I got the old value


int cptError = 0;
            Console.WriteLine("");
            try                 {   Console.WriteLine("Erreur TtShortname : " + tt.TtShortname.ToString());cptError++;  } 
            catch(Exception e)  {   Console.WriteLine("TtShortname access ok : " + e.Message);}

            try                 {   Console.WriteLine("Erreur TpId : " + tt.TpId.ToString());   cptError++;     } 
            catch(Exception e)  {   Console.WriteLine("TpId access ok : " + e.Message);}

            try                 {   Console.WriteLine("Erreur TtMonday : " + tt.TtMonday.ToString()); cptError++;} 
            catch(Exception e)  {   Console.WriteLine("TtMonday access ok : " + e.Message);}
            
            try                 {   Console.WriteLine("Erreur TtDaysPerWeek : " + tt.TtDaysPerWeek.ToString()); cptError++; } 
            catch(Exception e)  {   Console.WriteLine("TtDaysPerWeek access ok : " + e.Message);}
            
            
            if (cptError > 0)
                Assert.Fail("Some errors occurred when accessing properties");

And then I got :

TestCase 'HRATestCenter.HRADataLayer.llblgenTest.TestSetNullForNew' failed: Some errors occurred when accessing properties
Out: 
Erreur TtShortname : 
Erreur TpId : 0
Erreur TtMonday : 21/10/2004 0:00:00
Erreur TtDaysPerWeek : 0

But I've tested the save and in database it's the correct value, so it's ok on this side.

Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 21-Oct-2004 12:09:59   

IsNull returns true if the READ value from the database was NULL. So setting the field's value to null doesn't return true for IsNull then.

Ok I understand. But it's not very logic for me simple_smile field.IsNull should return true if the field is really null Maybe field.IsDbNull should return actual IsNull simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 21-Oct-2004 12:24:12   

Fabrice wrote:

I try to access the field below the code I've put (I've not put all code) When I make SetNewFieldValue and then I try to access to the fiels, I got the old value


int cptError = 0;
            Console.WriteLine("");
            try                 {   Console.WriteLine("Erreur TtShortname : " + tt.TtShortname.ToString());cptError++;  } 
            catch(Exception e)  {   Console.WriteLine("TtShortname access ok : " + e.Message);}

            try                 {   Console.WriteLine("Erreur TpId : " + tt.TpId.ToString());   cptError++;     } 
            catch(Exception e)  {   Console.WriteLine("TpId access ok : " + e.Message);}

            try                 {   Console.WriteLine("Erreur TtMonday : " + tt.TtMonday.ToString()); cptError++;} 
            catch(Exception e)  {   Console.WriteLine("TtMonday access ok : " + e.Message);}
            
            try                 {   Console.WriteLine("Erreur TtDaysPerWeek : " + tt.TtDaysPerWeek.ToString()); cptError++; } 
            catch(Exception e)  {   Console.WriteLine("TtDaysPerWeek access ok : " + e.Message);}
            
            
            if (cptError > 0)
                Assert.Fail("Some errors occurred when accessing properties");

And then I got :

TestCase 'HRATestCenter.HRADataLayer.llblgenTest.TestSetNullForNew' failed: Some errors occurred when accessing properties
Out: 
Erreur TtShortname : 
Erreur TpId : 0
Erreur TtMonday : 21/10/2004 0:00:00
Erreur TtDaysPerWeek : 0

But I've tested the save and in database it's the correct value, so it's ok on this side.

I'm not sure I understand the tests. Better tests would be: tt.TtDaysPerWeek==tt.Fields[(int)entityFieldIndex.TtDaysPerWeek].CurrentValue;

Fabrice wrote:

IsNull returns true if the READ value from the database was NULL. So setting the field's value to null doesn't return true for IsNull then.

Ok I understand. But it's not very logic for me simple_smile field.IsNull should return true if the field is really null Maybe field.IsDbNull should return actual IsNull simple_smile

I had a hard time finding a good name myself simple_smile The philosophy was and still is: the entity in memory can't work with null/Nothing. The entity in memory is a mirror of the entity in the database. This means that flags for NULL reporting should signal the situation in the database, as that's what you're interested in: you read an entity into memory and you want to check if a field in the database was NULL.

But there isn't a clear solution for this which is clear to everybody unless nullable types are used for the field types.

Frans Bouma | Lead developer LLBLGen Pro
Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 21-Oct-2004 12:37:47   
I'm not sure I understand the tests. Better tests would be:
tt.TtDaysPerWeek==tt.Fields[(int)entityFieldIndex.TtDaysPerWeek].CurrentValue; 

The test show 1 thing : when you set a field to null, and then you access the field (entity.field) you don't have any exception (like typed datarow). Instead, you get the OLD value (before the set field to null).

It's a normal behaviour ? I'm almost sure in the previous version of llblgen I got exception when trying to access to a field set to null via SetNewFieldValue. And for me it's normal to get an exception simple_smile

(Thanks for you explanation simple_smile )

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 21-Oct-2004 12:55:30   

Fabrice wrote:

I'm not sure I understand the tests. Better tests would be:
tt.TtDaysPerWeek==tt.Fields[(int)entityFieldIndex.TtDaysPerWeek].CurrentValue; 

The test show 1 thing : when you set a field to null, and then you access the field (entity.field) you don't have any exception (like typed datarow). Instead, you get the OLD value (before the set field to null).

It's a normal behaviour ? I'm almost sure in the previous version of llblgen I got exception when trying to access to a field set to null via SetNewFieldValue. And for me it's normal to get an exception simple_smile

(Thanks for you explanation simple_smile )

When the field is null, you get the default value for the field back. This is added in 1.0.2003.3 if I'm not mistaken. The reason for this is that when you set a field to null and the field is in an entity which is bound to a grid, the grid goes bezerk because of hte exception.

Frans Bouma | Lead developer LLBLGen Pro
Fabrice
User
Posts: 180
Joined: 25-May-2004
# Posted on: 21-Oct-2004 13:19:57   

When the field is null, you get the default value for the field back. This is added in 1.0.2003.3 if I'm not mistaken. The reason for this is that when you set a field to null and the field is in an entity which is bound to a grid, the grid goes bezerk because of hte exception

Should be nice to configure this behaviour simple_smile To allow an exception or return the old value like now. Because for me having a exception is a way to detect where I forgot to test the CurrentValue.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 21-Oct-2004 13:29:35   

Fabrice wrote:

When the field is null, you get the default value for the field back. This is added in 1.0.2003.3 if I'm not mistaken. The reason for this is that when you set a field to null and the field is in an entity which is bound to a grid, the grid goes bezerk because of hte exception

Should be nice to configure this behaviour simple_smile To allow an exception or return the old value like now. Because for me having a exception is a way to detect where I forgot to test the CurrentValue.

This situation happens only if you set a field to null explicitly AND you read back the value. You should get the default value, as when you save the entity and read it back, you also get the default value.

Frans Bouma | Lead developer LLBLGen Pro
ww
User
Posts: 83
Joined: 01-Oct-2004
# Posted on: 21-Oct-2004 20:15:58   

Otis wrote:

A fix for this is now available in the form of an update to the hotfix for the runtime libraries 1.0.2004.1. The hotfix will be rolled into the installer at the end of the day.

That was quick. Thanks.