PropertyChanged event not firing for DB-generated IDs

Posts   
 
    
philipp
User
Posts: 53
Joined: 15-Feb-2007
# Posted on: 01-Oct-2007 00:00:48   

Hi there

The following test fails at the last line - it appears that LLBLGen does not fire the PropertyChanged event if it updates an entity ID after a save/refetch. The entity runs agains Firebird, the ID is generated by a generator which is invoked by LLBLGen. Is this supposed to work like this and if yes: What's the best pattern to conveniently get this change as well for auditing purposes?

//[Test]
public void TestPropertyEvents()
{
  //init group
  GroupEntity group = new GroupEntity();
  group.QualifiedName = "hello world";
  Assert.AreEqual(0, group.GroupId);

  //register event listener and count events
  int eventCount = 0;
  group.PropertyChanged += delegate { eventCount++; };

  using (DataAccessAdapter adapter = TestUtil.CreateAdapter())
  {
    Assert.IsTrue(adapter.SaveEntity(group, true));
  }

  //group ID changed?
  Assert.AreNotEqual(0, group.GroupId);
  //event fired?
  Assert.AreEqual(1, eventCount, "ALWAYS FAILS - COUNTER IS 0);
}

btw: I noticed that I NEED to set at least one property (the _QualifiedName _in the test above). If I just try to save an empty (default) entity, LLBL does nothing at all, but _SaveEntity _still returns true. Took me quite a while to figure out what was happening. I'm aware that this is somewhat artificial, but just wanted to let you know...

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 01-Oct-2007 05:45:18   

Hi philipp,

it appears that LLBLGen does not fire the PropertyChanged event if it updates an entity ID after a save/refetch

The PropertyChanged is fired when a change in triggered by code (user or system) in the entity, so when the entity is updated or filled no PropertyChanged is called.

Is this supposed to work like this and if yes: What's the best pattern to conveniently get this change as well for auditing purposes?

If you are using LLBLGenPro v2.5 the best way is to use the new Auditing feature. If not, you can use AfterSave event.

btw: I noticed that I NEED to set at least one property (the QualifiedName in the test above). If I just try to save an empty (default) entity, LLBL does nothing at all, but SaveEntity still returns true. Took me quite a while to figure out what was happening. I'm aware that this is somewhat artificial, but just wanted to let you know...

Yes. The Save routine didn't fail and it has nothing to do because no field has set, so no exception throws.

David Elizondo | LLBLGen Support Team
philipp
User
Posts: 53
Joined: 15-Feb-2007
# Posted on: 01-Oct-2007 09:52:04   

Hi daelmo

Thanks for the fast reply! simple_smile

daelmo wrote:

The PropertyChanged is fired when a change in triggered by code (user or system) in the entity, so when the entity is updated or filled no PropertyChanged is called.

I understand. However, is this desirable? I mean, LLBLGen explicitely wants me to perform a refetch after saving (for good reason!) because otherwise, my entities may go out of sync. But if the changed properties do not raise events after a refetch, wouldn't this cause issues with data binding?

Cheers Philipp

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 01-Oct-2007 12:10:01   

(deleted text, I thought this was about fk syncing, which isn't the case. )

(edit). The event is for databinding purposes, not for resyncing, because the ID is set despite the fact if the entity is refetched or not. (this is done to save you a roundtrip if you just want to know the ID).

It's true that the event isn't raised for the ID being set. Enabling this has consequences: related entities will also raise their fields mapped onto related fields events if they map this field etc. So I'll add this to v2.6 as a breaking change update. If the side effects are undesirable, it won't be added (it's not there since september 2003 and you're the first person who asks for it wink )

Frans Bouma | Lead developer LLBLGen Pro
philipp
User
Posts: 53
Joined: 15-Feb-2007
# Posted on: 01-Oct-2007 12:45:47   

Thanks for considering it! simple_smile

philipp
User
Posts: 53
Joined: 15-Feb-2007
# Posted on: 02-Oct-2007 03:07:37   

One more thing flushed

I'm having the same issue with auditing (AuditEntityFieldSet is not being invoked). It looks like I would have to set up a custom housekeeping strategy for DB-generated content using Auditors plus some custom logic I'll perform before / after saving my entities.

And a related thing is changed FKs - would have been nice to get an auditing event for updated FKs due to referencing which would have made is very easy to determine the previous and new parent of my entity just based on field values. Guessing the alternative is handling the (de)referencing methods in the auditor, but this is much harder compared to just checking the FK...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 03-Oct-2007 10:13:09   

philipp wrote:

One more thing flushed

I'm having the same issue with auditing (AuditEntityFieldSet is not being invoked). It looks like I would have to set up a custom housekeeping strategy for DB-generated content using Auditors plus some custom logic I'll perform before / after saving my entities.

Will take this into account as well.

And a related thing is changed FKs - would have been nice to get an auditing event for updated FKs due to referencing which would have made is very easy to determine the previous and new parent of my entity just based on field values. Guessing the alternative is handling the (de)referencing methods in the auditor, but this is much harder compared to just checking the FK...

The de-referencing/referencing auditing actions are meant for this, as they do the same thing, so we didn't implement the FK sync action also, because that would be the same. Why is the dereferencing/referencing action hard to use, could you elaborate on that a bit?

Frans Bouma | Lead developer LLBLGen Pro
philipp
User
Posts: 53
Joined: 15-Feb-2007
# Posted on: 03-Oct-2007 10:59:12   

Otis wrote:

The de-referencing/referencing auditing actions are meant for this, as they do the same thing, so we didn't implement the FK sync action also, because that would be the same. Why is the dereferencing/referencing action hard to use, could you elaborate on that a bit?

It's not very hard, but just not that convenient. A housekeeping method that submits me an FK key change gives me all information at once, while two independent events in a shared auditor lack this state information which can make it hard to follow changes (item A was moved from X to Y) in some cases. I guess, that's the main issue- I ended up skipping auditing for some scenarios and just implementing custom logic on the upper layer.

A related problem that may bother developers is that I cannot always count on a referencing after a dereferencing occurs. Just imagine a _Category _table with an FK that refers to the PK of its own (subcategory -> category): If I decide to move a sub category to the top level (or vice versa), I only get one of these events.

Cheers, Philipp

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 04-Oct-2007 14:13:51   

philipp wrote:

Otis wrote:

The de-referencing/referencing auditing actions are meant for this, as they do the same thing, so we didn't implement the FK sync action also, because that would be the same. Why is the dereferencing/referencing action hard to use, could you elaborate on that a bit?

It's not very hard, but just not that convenient. A housekeeping method that submits me an FK key change gives me all information at once, while two independent events in a shared auditor lack this state information which can make it hard to follow changes (item A was moved from X to Y) in some cases. I guess, that's the main issue- I ended up skipping auditing for some scenarios and just implementing custom logic on the upper layer.

The auditor doesn't have to be shared. The main purpose of the auditor is that info is logged. Afterwards you do analysis on it, you shouldn't do that in the auditor, that's just the logger, the messenger simple_smile

A related problem that may bother developers is that I cannot always count on a referencing after a dereferencing occurs. Just imagine a _Category _table with an FK that refers to the PK of its own (subcategory -> category): If I decide to move a sub category to the top level (or vice versa), I only get one of these events.

Though the conclusion from that fact is exactly the knowledge what happened.

Frans Bouma | Lead developer LLBLGen Pro