Allow setting a field when adding record but not when updating

Posts   
 
    
clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 13-Mar-2012 21:44:17   

I have a manager class for our entities that have methods for Adding and Updating an entity. They are of the form:

bool Add(SomeEntity theEntity) bool Update(SomeEntity theEntity)

In the XML documenation for the Add(), I instruct the programmer to create an empty entity, fill in the fields, and then call Add().

In the XML documenation for the Update(), I instruct the programmer to fetch an existing entity, update the fields, then call Update().

However, there are some entity fields that I allow the programmer to set during an Add() operation that I want to prevent them from changing during an Update() operation. How can I enforce this policy?

One idea I though of doing was adding a pre-condition (assertion) check to the manager class Update() method which checks if the forbidden field was changed or not. If it was, that would at least alert the programmer that he isn't doing the process correctly.

I also noticed there is a RejectChange() method on EntityField2. Can I use that to undo the change and restore the original value? How do I use this?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 14-Mar-2012 07:05:05   

What LLBLGen version are you using?

I think that RejectChange was moved to be private/protected. I would recommendo you these options:

A. Detect if the field has been changed, if so, raise an error, or set the current value to the db original one:

if (entityToUpdate.Fields["X"].IsChanged)
{
    entityToUpdate.SetNewFieldValue("X", entityToUpdate.Fields["X"].DbValue);
}

B. Use Validators. You use the ValidateEntityBeforeSave method, inside you can check whether it's an update if the entity .IsNew property is false. Then compare the values and raise an exception if some forbidden field was changed..

David Elizondo | LLBLGen Support Team
clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 14-Mar-2012 16:16:47   

daelmo wrote:

What LLBLGen version are you using?

I think that RejectChange was moved to be private/protected.

I using version 2.6. I won't use RejectChange.

daelmo wrote:

I would recommendo you these options:

A. Detect if the field has been changed, if so, raise an error, or set the current value to the db original one:

if (entityToUpdate.Fields["X"].IsChanged)
{
    entityToUpdate.SetNewFieldValue("X", entityToUpdate.Fields["X"].DbValue);
}

B. Use Validators. You use the ValidateEntityBeforeSave method, inside you can check whether it's an update if the entity .IsNew property is false. Then compare the values and raise an exception if some forbidden field was changed..

OK, these seem like good options. Thanks.

I was wondering, is there a way to add to the XML comment generated for an Entity field. It would be nice if I could say "Only set this field for new entities, do not set when updating an existing entity".

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 14-Mar-2012 16:52:28   

I was wondering, is there a way to add to the XML comment generated for an Entity field. It would be nice if I could say "Only set this field for new entities, do not set when updating an existing entity".

Where do you want to show this? Is this for the Developer or the users?

clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 14-Mar-2012 16:58:44   

Walaa wrote:

I was wondering, is there a way to add to the XML comment generated for an Entity field. It would be nice if I could say "Only set this field for new entities, do not set when updating an existing entity".

Where do you want to show this? Is this for the Developer or the users?

For the developers. I was hoping developers would see my additional comments when the XML comment for an entity field is displayed as a tooltip in Visual Studio as they are typing their code.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 15-Mar-2012 10:16:43   

AFAIK, you can specify "/doc" as a compiler option, for the generated code project.

Then VS takes care of the following: When compiling the project an xml file should be created with all code comments, the xml file shoulod have the same name as the output binary file, and be placed in the same folder. From which Visual Studio uses this xml file to display intellisense tooltips.

clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 15-Mar-2012 15:55:16   

Walaa wrote:

AFAIK, you can specify "/doc" as a compiler option, for the generated code project.

Then VS takes care of the following: When compiling the project an xml file should be created with all code comments, the xml file shoulod have the same name as the output binary file, and be placed in the same folder. From which Visual Studio uses this xml file to display intellisense tooltips.

I understand that and it already does that.

What I'm trying to say is that LLBLGen has XML comments in the generated code.
Example:


/// <summary> The TaxYear property of the Entity EqualizedValueSchoolTaxRate<br/><br/>
/// </summary>
/// <remarks>Mapped on  table field: "EqualizedValueSchoolTaxRate"."TaxYear"<br/>
/// Table field type characteristics (type, precision, scale, length): SmallInt, 5, 0, 0<br/>
/// Table field behavior characteristics (is nullable, is PK, is identity): false, false, false</remarks>
public virtual System.Int16 TaxYear
{
    get { return (System.Int16)GetValue((int)EqualizedValueSchoolTaxRateFieldIndex.TaxYear, true); }
    set { SetValue((int)EqualizedValueSchoolTaxRateFieldIndex.TaxYear, value); }
}

I was hoping there was a way I could add my own comment to that generated XML comment that says "Do not set this field for existing entities". Obviously, I could modify the XML comments in the generated files, but then I will lose those changes every time I regenerate the code. I was hoping I could put additional comments for a method in the partial class file where I put my custom code. But after doing some research online, I learned you can't do that.

So consider this thread closed.

Thanks.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 15-Mar-2012 16:16:11   

The only way it occurs to me is defining a custom framework settings named "additional field comment" to the field level. Then in the designer you could set this setting on fields. Then you have to modify a little bit the templates to add this additional comment to the generated field. To learn more about this read Defining and consuming custom settings

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39909
Joined: 17-Aug-2003
# Posted on: 15-Mar-2012 16:29:37   

Actually it's already build in. simple_smile

Define custom properties (in the entity editor) on the field. Each name-value pair will be emitted in the XML comments on the property of the field simple_smile

btw, I think you should add code to prevent this from happening anyway instead of just docs. You could add a validator which checks whether the field should be set and if it violates the rule, throw an exception.

Frans Bouma | Lead developer LLBLGen Pro
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 15-Mar-2012 16:34:05   

I just remember the easy way to do it: Use custom properties.

You can see the custom properties when you edit and entity and then go to "Code gen. info" sub tab, in there find the "Custom properties tab". You can add custom properties to the entity or/and to the entity fields. Those custom properties are added as additional comments in the summary for your fields. This is an example of a custom property set to the BirthDate field of the Employee entity:

/// <summary> The BirthDate property of the Entity Employee<br/><br/>
/// Reminder: Don't set this property for updates<br/></summary>
/// <remarks>Mapped on  table field: "Employees"."BirthDate"<br/>
/// Table field type characteristics (type, precision, scale, length): DateTime, 0, 0, 0<br/>
/// Table field behavior characteristics (is nullable, is PK, is identity): true, false, false</remarks>
public virtual Nullable<System.DateTime> BirthDate
{
    get { return (Nullable<System.DateTime>)GetValue((int)EmployeeFieldIndex.BirthDate, false); }
    set { SetValue((int)EmployeeFieldIndex.BirthDate, value); }
}

See this on the docs

David Elizondo | LLBLGen Support Team
clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 15-Mar-2012 16:39:05   

I guess I tried to shut down the thread prematurely! Thanks for the information about custom properties.

As for preventing the user from changing the field in the first place I decided to use an assertion check. In case the programmer ignores the assertion violation, it's no big deal since I wrote code to undo their change and restore it to the original DBValue.

I didn't want to throw an exception because that is something a customer would see and it's really not a problem they can do anything about. I like to use assertions to alert programmers to the fact that they are using the code incorrectly.

We had been debating whether to enforce the rule in a Validator or in an override of PreProcessValueToSet(). What are the pros and cons of either approach? We currently are using PreProcessValueToSet() since we are actually changing the data (restoring its original value) as opposed to just validating it.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 15-Mar-2012 20:36:02   

clint wrote:

I guess I tried to shut down the thread prematurely! Thanks for the information about custom properties.

Yes, I forget that this is actually built-in.

clint wrote:

We had been debating whether to enforce the rule in a Validator or in an override of PreProcessValueToSet(). What are the pros and cons of either approach? We currently are using PreProcessValueToSet() since we are actually changing the data (restoring its original value) as opposed to just validating it.

Yes, it's a debatable subject. In fact there certain things that should be enforced just with a developer convention. The thing with PreProcessValueToSet is that, if the developer change some field that shouldn't be changed, you fix it in that method but the programmer still thinks he changed it, later in the code he could use that assumption. Another tricky situation is when you use the entity to do an UpdateMulti. Imagine that you need to do something like this:

var newValuesOfOder = new OrderEntity();
newValuesOfOder.OrderDate = Datetime.Now;

// updates the orderDate of all orders from Customer ALFKI.
adapter.UpdateEntitiesDirectly(newValuesOfOrder, (OrderFields.CustomerId == "ALFKI");

That could be a problem because you pre-processed the value you want to update. There are other scenarios from which you might want to actually update the value, like a superuser making a necessary change in the data.

So, it's up to your needs, you can use a convention, use pre/postProcessValueToSet, use a validator, use a rule in the business logic, even use a validation in the GUI. Or any combination of all those.

David Elizondo | LLBLGen Support Team