ReadOnly fields modified using ForcedCurrentValueWrite / IsChanged is not saved in DB

Posts   
 
    
Max avatar
Max
User
Posts: 221
Joined: 14-Jul-2006
# Posted on: 28-Nov-2008 14:50:51   

I have an entity (PersonaTitoloStudioEntity) with one readonly field (TitoloStudio). In the OnFieldValueChanged I set this readonly field to a value taken from an internal lookup table.

I set the value on the readonly field using ForcedCurrentValueWrite and setting IsChanged to True:

Partial Public Class PersonaTitoloStudioEntity

    Protected Overrides Sub OnFieldValueChanged(ByVal originalValue As Object, ByVal field As SD.LLBLGen.Pro.ORMSupportClasses.IEntityField2)
        MyBase.OnFieldValueChanged(originalValue, field)

        If DirectCast(field.FieldIndex, PersonaTitoloStudioFieldIndex) = PersonaTitoloStudioFieldIndex.IdtitoloStudio Then

            Dim titoloStudioValue As String
            'titoloStudioValue = GetTitoloStudioValueFromLookupTable(field.CurrentValue)
            titoloStudioValue = "...this is a test string..."

            Me.Fields(PersonaTitoloStudioFieldIndex.TitoloStudio).ForcedCurrentValueWrite(titoloStudioValue)
            Me.Fields(PersonaTitoloStudioFieldIndex.TitoloStudio).IsChanged = True

        End If

    End Sub

End Class

But this value in the readonly field isn't persisted to the DB.

This is a new entity, so LLBLGen generate an INSERT INTO, but in this SQL the TitoloStudio field/value are missing.

I've also checked during the OnBeforeEntitySave event, and my readonly field has the correct value, and is marked as changed.

Maybe I'm doing something wrong?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 29-Nov-2008 00:17:39   

Mmm. Indeed, this (where Fax is marked as read only):

CustomerEntity newCustomer = new CustomersEntity();
newCustomer.CustomerId = "AAAA";
newCustomer.CompanyName = "AAAAAAAAAAAAAA";
newCustomer.Fields["Fax"].ForcedCurrentValueWrite("1122334455");
newCustomer.Fields["Fax"].IsChanged = true;
            
using (DataAccessAdapter adapter = new DataAccessAdapter())
{
    adapter.SaveEntity(newCustomer);
}

Generates this:

Query: INSERT INTO [Northwind].[dbo].[Customers] ([CustomerID], [CompanyName])  VALUES (@CustomerId, @CompanyName)
Parameter: @CustomerId : StringFixedLength. Length: 5. Precision: 0. Scale: 0. Direction: Input. Value: "AAAA".
Parameter: @CompanyName : String. Length: 40. Precision: 0. Scale: 0. Direction: Input. Value: "AAAAAAAAAAAAAA".

I never faced this, so, looking at the documentation here:

If you want to set an identity primary key column, you'll notice you can't do that because it is marked as read-only. Use the method entityObject.Fields[fieldindex or fieldname].ForcedCurrentValueWrite(value). See the reference manual for details about this method (EntityField2.ForcedCurrentValueWrite).

and here:

When you've selected a field which is not read-only by default (an identity field, a field of a database type which doesn't require a value (like SqlServer's Timestamp) or a computed column), you're able to make the field read-only by checking the Is readonly checkbox.

Seems that indeed the ForcedCurrentValueWrite is intended to a workaround for identity fields that for any reason you want to write. Also, the ReadOnly is designed for fields that are, in fact, read-only (calculated fields, timestamp, etc).

Why your field is marked as read only?

I'll try to find a workaround for you.

David Elizondo | LLBLGen Support Team
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 29-Nov-2008 00:49:33   

Ok. I investigate and I concluded that that is not supported (changed a read-only field that isn't identity). The framework doesn't include these kind of fields at the save action. There exists a method at DQE that evaluate this (_CheckIfFieldNeedsInsertAction_).

I.W.O. this satisfy the read-only concept. So, if you need to change it, it isn't really read-only in practice simple_smile

David Elizondo | LLBLGen Support Team
Max avatar
Max
User
Posts: 221
Joined: 14-Jul-2006
# Posted on: 01-Dec-2008 09:34:43   

daelmo wrote:

Ok. I investigate and I concluded that that is not supported (changed a read-only field that isn't identity). The framework doesn't include these kind of fields at the save action. There exists a method at DQE that evaluate this (_CheckIfFieldNeedsInsertAction_).

I.W.O. this satisfy the read-only concept. So, if you need to change it, it isn't really read-only in practice simple_smile

Thanks for the explanation.

I've made some fields read-only because I want to make clear (to the other developers) that these fields aren't updatable from the end user of the entity, and I also want to be sure that winform binding will never be able to update those fields. These fields are intended to be updated only from the code I write inside the entity class. These fields will be filled with a value based on the others updatable fields. But I want to be sure that only the code I wrote inside the entity is able to update those readonly fields.

Does this make sense?

Do you know if there are other way to attain this result?

Thanks, Max

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 01-Dec-2008 11:15:37   

The workaround that I can think of is:

1- Remove the read-Only flag from the designer and regenerate the code. 2- Use a validator class and implement ValidateFieldValue and deny any set to this field. 3- The above validator should be used at the UI code. 4- In the BL code, you may unset the validator to be able to set the specified field. 5- Or better use DI Scopes to use another validator for the BL rather than the one use at the UI.

Read about DI Scopes here

Max avatar
Max
User
Posts: 221
Joined: 14-Jul-2006
# Posted on: 01-Dec-2008 11:52:04   

Walaa wrote:

The workaround that I can think of is:

1- Remove the read-Only flag from the designer and regenerate the code. 2- Use a validator class and implement ValidateFieldValue and deny any set to this field. 3- The above validator should be used at the UI code. 4- In the BL code, you may unset the validator to be able to set the specified field. 5- Or better use DI Scopes to use another validator for the BL rather than the one use at the UI.

Read about DI Scopes here

Unsetting the the validator in the BL code should work, Thanks simple_smile