using IsChangedInThisEditCycle not working for me

Posts   
 
    
Kris Nobels avatar
Posts: 118
Joined: 02-Apr-2008
# Posted on: 23-Feb-2017 16:19:03   

I have a question about entity.Fields.IsChangedInThisEditCycle = true;

I work with dto's in combination with automapper.

But the problem kicks in when a value is changed to null.

The Entity property does not know if it changed in case the value is null.

So what i do is this:

CustomerEntity entity = M.Map<CustomerDTO, CustomerEntity>(dto);

            var adapter = new DataAccessAdapter();
            try
            {

                //Explicit update all fields
                entity.Fields.IsChangedInThisEditCycle = true;

                adapter.SaveEntity(entity, true);
            }
            finally
            {
                adapter.Dispose();
            }

            return dto;

But the value remains untouched at the database.

What do i forget or is wrong?

Because my interpretation is that for all fiels in entity the state is changed to "True". (that is what i need) simple_smile

In my other test i do Here i get my expected result.

entity.Fields["Mobile"].IsChanged = true;

https://www.llblgen.com/documentation/5.0/ReferenceManuals/LLBLGenProRTF/html/7227A830.htm

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 23-Feb-2017 23:37:34   

IsChangedInThisEditCycle is only useful in DataBinding scenarios. i.e. edit cycles of a bound control.

Instead as you figured out, use the .Fields["FieldName"].IsChanged

Kris Nobels avatar
Posts: 118
Joined: 02-Apr-2008
# Posted on: 24-Feb-2017 08:10:38   

So the only solution here is:

Loop to the properties of the entity change state to "ischanged" and save ?

Is there no setting field in LLBLgen to behave for NULL fields ?

Like always perform update on NULL fields ?

Dirty solution is to make your fields with empty strings, instead of null fields.

That's the reason i asking this question to the Experts of llblgen :-)

I am searching for a long term solution here ...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39616
Joined: 17-Aug-2003
# Posted on: 24-Feb-2017 10:55:13   

Kris wrote:

So the only solution here is:

Loop to the properties of the entity change state to "ischanged" and save ?

Is there no setting field in LLBLgen to behave for NULL fields ?

Like always perform update on NULL fields ?

Dirty solution is to make your fields with empty strings, instead of null fields.

That's the reason i asking this question to the Experts of llblgen :-)

I am searching for a long term solution here ...

Set IsChanged to true for each field you want to see changed, is the way to trick the framework to save a field without setting it to a value.

I'm not familiar with how automapper's Map works, so if I understand it correctly: the Map function updates an entity instance with the values of the DTO instance and your problem now is that if the value in the DTO is null, the field in the entity isn't set to null ?

Or does map create a new instance of the entity, and sets it to the values of the DTO?

I'm asking this to get to the bottom of the null-set problem: if you set a field in an existing entity to null, and it had a value before setting it to null, the field gets updated, hence my question.

Frans Bouma | Lead developer LLBLGen Pro
Kris Nobels avatar
Posts: 118
Joined: 02-Apr-2008
# Posted on: 27-Feb-2017 15:16:58   

Hello,

I provide some sceenshot's of my unit test.

In the unit test i show you how i create the case.

If we use string.empty -> no problem at all.

if we change this to null -> Entity thinks it not changed.

Because if we map 1 existing DTO -> new Entity it is not aware of changes before.

automappers wil set values of null, but for LLBLgen entity nothing is changed.

Attachments
Filename File size Added on Approval
sshot-515a.png 40,180 27-Feb-2017 15:17.35 Approved
sshot-516a.png 54,360 27-Feb-2017 15:17.52 Approved
Kris Nobels avatar
Posts: 118
Joined: 02-Apr-2008
# Posted on: 27-Feb-2017 19:29:14   

Currently my fix is this


public static class LLBLgenExtentions
    {
        public static EntityBase2 SetNull2Changed(this EntityBase2 entity)
        {
            foreach (IEntityFieldCore field in entity.Fields)
            {
                if (!field.IsPrimaryKey && field.CurrentValue == null)
                {
                    field.IsChanged = true;
                };              
            }

            return entity;
        }
    }

Other solution (i don't like, needs extra call to DB)

  • fetch entity by pk
  • Use automapper to push data from DTO to entity (And state is changed)
  • Save entity
Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 28-Feb-2017 02:28:57   

An Entity is a representation to a database entity. An entity only needs to be aware of a field's current value and the db value (if exists), so when updating or inserting it can decide whether a save is required for that field or not. There is no need to track transient state from an entity point of view.

Kris Nobels avatar
Posts: 118
Joined: 02-Apr-2008
# Posted on: 28-Feb-2017 11:54:12   

OK, you are just telling the purpose of things) simple_smile

The problem is when using DTO's in combination automapper you fill a new entity with data from **existing **dto.

In this way it's saving it -> LLBgen performs update. (or otherwise insert)

The pitfall is null values, DTO value is NULL -> new Entity field by default is NULL (LLBLgen entity field state is -> nothing changed)

But if we need to change an existing record in the database -> DTO value from "TEST text" to null.

The field remains the same in Database.

When we map this -> llblgen does not know if it's changed or not. (DTO does not keep track of state)

If we retrieve the object first, then we map the dto against entity -> there is a working solution as well. (Downside is -> 2 calls to the database, instead of 1)

Is my design that bad ?

I can not use LLBLgen entity's everywhere in my solution that's the problem.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 28-Feb-2017 15:14:15   

If you are using DTOs which is ok, you don't have the change tracking that the entity provides.

So the only workaround, is to assume all fields has been changed, and so you'd loop on the fields and set the IsChanged property to true for all.

This is not specific to null values, it's the same issue with values that's equal to the same default value for the type of the field.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39616
Joined: 17-Aug-2003
# Posted on: 28-Feb-2017 16:46:37   

In your situation, the extension method is the way to solve it indeed, there's no other way as all values look like they're new and null values don't have to be set.

There's no 'ideal' way to solve this. For our DTO system we opted for the fetch entity -> update fields -> save, route, as it can be beneficial to do so (if no fields are changed, you don't get a save, which might keep things in check like 'IsChanged' fields etc.) and it behaves as expected in all cases, but indeed at the price of a roundtrip. As a fetch of an entity is < 0,60ms per entity (over the network!) in our benchmarks (https://github.com/FransBouma/RawDataAccessBencher/blob/master/Results/2016-11-22.txt#L105) I think it's worth it. But your situation might vary of course, so it's up to you what to choose.

Frans Bouma | Lead developer LLBLGen Pro
Kris Nobels avatar
Posts: 118
Joined: 02-Apr-2008
# Posted on: 28-Feb-2017 20:44:27   

Thanks for the feedback !