This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hi all, I'm having some issues I could use a hand with. I'm building invoices via a batch process. I want to sum them in the batch process so that displays to the user perform no calculations only display. To increase the effieciency as our invoices can get quite large (3k + line items), I only calculate the total during the OnSaving event. I have the following object tree. Invoice is essentially the root node in the structure.
Invoice -> * SpiderSummary -> TrackLineItems ->Track Invoice -> * UserSummary -> *NotificationLineItems -> NotificationMessage Invoice -> * UserSummary -> *TextMessageLineItems -> TextMessage
This works really well for the the initial transaction when I create an invoice. However, on subsequent transactions with new line item additions, my Invoice (correctly) doesn't have an EntityState that requires a Save because nothing on the Invoice itself has changed. However, something within it's object graph has, and I need to update it's values pre-persist.
I've created an internal function within my invoice called Calculate(), which OnSaving within invoice calls. I also call this via my Summary Items in the following way.
//if we have an invoice and we have updated this object, force the invoice to recalc
This correctly calculates the total on the invoice, but the SQL update statement is never executed. Is the OnSaving fired too late to change the EntityState to Modifed and force the invoice to be persisted?
Also, is there a better way for me to signal to LS that an object needs saved? If I could explicity tell LS to "Re-save object <x>" I could avoid a lot of the issues I'm having.
Thanks, Todd
|
|
|
You could do it in your LineItem classes. The line item entities will have backreferences to the summary objects and through them to the Invoice object. Detecting adding and removing line items it is a bit more fiddly but you can do this in your summary classes by handling the ItemAdded and ItemRemoved events on the entity collections. In fact you could centralise the logic in the summary classes by having the summary classes handle the PropertyChanged event from the child line items, though this could be a bit fiddly. |
|
|
Thanks Ivan. I had a lot of event listeners, but it added quite a bit of code bloat for minimal functionality. To get around this issue, I've done the following.
Created this interface /// <summary>
then my invoice implements IUpdate, as well as my SpiderSummary, TrackLineItem etc. Then within each object (except Invoice), I've added the following LS event.
This has worked well, It allows me to bubble change events up to the highest level, invoice. However this still didn't resolve my issue of getting the entitystate of the invoice to Modified. In order to do that, my Update I have to have the following.
#region Implementation of IUpdate
Can I submit a feature request to add something like the following to IUnitOfWork?
IUnitOfWork.Modify(Entity e)
While this usually isn't needed, with the change of the behavior to transient values from version 2 to 3, I now have to internally modify the values in my objects to get them to persist in the callback. Having a call that would mark my EntityState as modifed and perform the save events would resolve this problem, without the need to randomly change values in my entity. If the impelmentation that intercepts value changes were to compare loaded values with current values, my work around would no longer function correctly. Having a way to explicity tell LS something needs re-persisted would ensure my code always works, regardless of the underlying implementation of the persistence engine.
Thanks, Todd |
|
|
You're right, OnEntityStateChanged is a better choice than hooking PropertyChanged events. We'll consider a "mark dirty" method for entities to force them to be included in a save, but there may be some implementation issues, specifically around LockVersion / partial saves, where we need to know *which* properties need saving. In the meantime, I'm afraid you'll have to continue with the "make a random change" trick. |
|
|
Hi Ivan, You have a very valid point. Perhaps a better definition of the functionaly I need is this.
"Notify entities when a persist is about to happen, regardless of my current entity state".
This way changes to persisted values wouldn't need to be tracked outside the existing mechanism. Any objects that have been loaded in the current unit of work regardless of entity state would receive the "public void PrepareSave(Event e)" event. This way, I could simply call re-calculate on my object before. This way I can recalucate my values right before everything is persisted, which would in turn allow me to have cleaner code.
Given that this event could potentially modify values, I would think the event response would need to signal to LS if it should re-validate the object given that bad code from this event could potentially create invalid data within the entity.
Thoughts?
|
|