Calculation before db update - jpa

I'm using Play Framework and I have what I think is a very frequent persistence problem :
I display a form with values coming from the database and a field 'quantity'
The user updates the form and changes the 'quantity' value
He clicks on the "save button"
In the controller method called, I want to get the old value of 'quantity' and calculate the difference between the new and the old one before updating the DB
To make that, i use findById (before calling the object.save method), but it gives me the new value, not the old one : it apparently looks into some cache (which one ?) instead of requesting the DB
=> is that a normal ? how can i get the old value, make my calculation and then persist ?
Thanks a lot for your help, I do not want to manage old/new value in my DB...i'm sure it's bad practice !
UPDATE
public static void save(#Valid Lot lot) {
History element = new History();
element.date = new Date();
//HERE below it returns the new value, not the old one
Lot databaseLot = Lot.findById(lot.id);
element.delta= databaseLot.quantity - lot.quantity;
element.save();
lot.save();
list(null, null, null, null);
}

This is because, Play is doing some magic for you here.
When you pass a JPA Object into your controller, that contains an ID, Play will automatically retrieve this JPA Object from the database. If you look here, it explains this in a little more detail. It states (and assuming an action call that is passing in a User JPA Pojo)
You can automatically bind a JPA object using the HTTP to Java
binding.
You can provide the user.id field yourself in the HTTP parameters.
When Play finds the id field, it loads the matching instance from the
database before editing it. The other parameters provided by the HTTP
request are then applied. So you can save it directly.
So, how can you fix this? I guess the easiest way is to not pass the id as part of the Pojo Object, and to pass the ID as a separate parameter, therefore Play will believe the object is not required to be automagically retrieved from the database.
An alternative method, is to have a setter method for the quantity field, which updates the delta. So, Play will automatically retrieve the object from the DB, then call your setter method to update the values (as per normal POJO binding), and as part of that operation, your new quantity, and the delta are set. Perfect! This is the best option in my opinion as it also ensures that the business logic stays neatly inside of your Model, and not your Controller.

I can't speak to the Play Framework specifically, but in JPA, the EntityManager caches objects for it's lifetime, unless explicitly emptied. Because of that, querying for an object that the context is already managing will just give you the cached version. Furthermore, it sounds like the EM you are getting is declared as EXTENDED, which causes the same EM to be used across multiple requests (or perhaps the framework does the lookup under the covers and sets the values before you get to handle it).
You will either need to work around this cache or configure Play to use a TRANSACTION-scoped Persistence Context (aka EntityManager). I can't help you with the latter, but the former is easy enough.
int newQuantity = entity.getQuantity();
entityManager.refresh(entity);
// enity.getQuantity() should now give you the old value
// Do your calculation
// entity.setQuantity(newQuantity);
At the end of the transaction, your new state should be saved.

You may save quantity value in a hidden text and you can process that

Related

Get list of changed properties on EF 4.2 Code Only

(sorry for my bad english)
Hey, I need to log all changes that happens on my database for auditing purposes. When I insert or delete a entity, it is easy but when I update something, I need to save what properties have changed and from/to what values. My domain service is a DbDomainService. How can I get the changes? Do I need to hit the database to see the old values and compare it myself?
There is more elegant means of doing this (e.g. Using Aspect coding techniques), but I had one isolated case in which I did this. This is the standard update for WCF RIA Services, on the server side, for each entity that you allow updates to occur.
public void UpdatePackingSlip(PackingSlip currentPackingSlip)
{
var BeforeUpdate_PackingSlip = this.ChangeSet.GetOriginal(currentPackingSlip);
//at this point you can compare the original values from the updated values, and capture
// whatever you want todo
Just make sure you don't change the code that attaches the object back to
the object context.

Why does updating an object only work one, particular way?

I am trying to update an object using EF4. An object is passed from the strongly-typed page to the action method and
[HttpPost]
public ActionResult Index(Scenario scenario, Person person)
{
// Some business logic.
// Update Scenario with Person information.
scenario.Person = person;
// Update the corresponding object and persist the changes.
// Note that the repository stems from the repository pattern. Contains the ObjectContext.
Scenario updateScenario = repository.GetScenario(scenario.ScenarioID);
updateScenario = scenario;
repository.Save();
}
However, the problem is that the changes do not persist when I do this. However, if I instead update every single property within the scenario individually and then persist the changes (via the Save method), everything is persisted.
I'm confused why this is happening. In my real application, there are MANY items and subobjects within a Scenario so it is not feasible to update every individual property. Can someone please help clear up what is happening and what I need to do to fix it?
In the context of your action method, you have two different objects of type Scenario. scenario points to one of the objects and updateScenario points to another one. With the line of code:
updateScenario = scenario
All you are doing is causing the updateScenario to point to the same object that scenario points to, you are not copying the values that make up the object from one to another. Essentially, your database context is aware of only 1 of the 2 instances of Scenario. The other instance of Scenario was created outside of the context and the context has not been made aware of it.
In your particular scenario you can accomplish what you want by not taking a Scenario on your parameter, and instead, pull the Scenario that you want to update from your database context and in your action method, invoke:
this.TryUpdateModel(updateScenario);
This will cause the model binder to update the property/fields on the Scenario object that your database context is aware of, and therefore will persist the changes when you call Save().
HTH

How can write to a change log when Entity Frameworks SaveChanges() is called?

I am using Entity Frameworks Code First. I have one entity that I need to keep a change history on. This entity has a double property and when it changes I need to record the amount change amount and date that it occurred. This means I need the old value the new value subtract and post ever time that value changes or when dbContect.SaveChanges() it called.
This project is really simple and I would like to keep it this way so I would prefer not add a service layer. I am simply making repository request in MVC controllers. (I know this is not pure but it is very agile)
How can I intercept changes to this entity so I can write to a change log?
You can listen for the ObjectContext.SavingChanges event, and then use the ObjectContext.ObjectStateManager property to look for the ObjectStateEntry(s) for the entity type that you are interested in.
ObjectStateEntry has properties to access the CurrentValues and OriginalValues, or only the original values for updatable properties using the GetUpdatableOriginalValues method.
Note: I have not tested this, but hopefully it will work for you.

Callbacks on entity on created/updated

I would like to know when entities in a certain database table are either created or updated. The application is essentially a CMS, and I need to know when changes are made to the content so that I can reindex them for searches.
I know that the autogenerated LINQ to EF class has overridable methods for when certain fields change, but I need to know when the whole object is created/updated, not just a single field. I tried putting it in OnCreated, only to find that meant OnObjectInitialized and not OnObjectInsertedIntoDBTable xD
I did some searching and came across this link. The "Entity State" section looks like its what I want, but I'm not sure how to use this information. Where do I override those methods?
Or perhaps there is a another/better way?
(I also need to know this for another part of the system, which will send notifications when certain content is changed. I would prefer this code to execute automatically when the insert/update occurs instead of placing it in a controller and hoping hoping I always call that method.)
You need to get ObjectStateEntry(s) from the ObjectStateManager property of the ObjectContect.
var objectStateEntries = this.ObjectStateManager.GetObjectStateEntries();
This entries contain every object state you've pulled down per context and what kind of actions where performed on them.
If you are using EF4 you can override the SaveChanges method to include this functionality. I've used this technique to audit every change that occurs in the database instead of triggers.

How can I update a single field from an entity with Entity Framework?

I need to load an object from the database, modify some of its fields and relations, and then I want to store a new value for only one field, without modifying the rest.
It would look something like this:
var thing = db.Things.First();
thing.Field1 = "asdas";
thing.Field2 = 23;
thing.OtherThings.Add(new OtherThing());
thing.FieldToUpdate = doSomething(thing);
db.SaveChanges();
But that would save all the changes, what I want is to only save FieldToUpdate...
I've looked around and all I've found is to use stored procedures, which seems like too much for something that looks so simple, besides I would have to make a different stored procedure for each time I need to do something like this...
My current solution is to open another context, load the thing again, update the FieldToUpdate and SaveChanges, but that's both inefficient and ugly.
If you want to do this with attached entity you have to update FieldToUpdate FIRST and call SaveChanges. Than you can update other fields and call SaveChanges again if needed. No other way with attached entity.
Other way you can try is to detach entity, modify what you want to (it will not track changes). Then attach entity back to context and call:
// I suppose that db is ObjectContext or inherited type
db.ObjectStateManager.GetObjectStateEntry(thing).SetModifiedProperty("FieldToUpdate");
Now only FieldToUpdate is tracked as changed.
The Entity Framework is smart enough to figure out what has changed and what hasn't and optimizes the SQL statement is uses accordingly. If you only change FieldToUpdate, then the SQL statement will only be an update on the single field, not on everything.
However, if you do change Field1 and Field2 from what they were originally, they will be persisted too, but ONLY if they changed. Otherwise, there's no need to tell the DB to change it to what it already is.
Entity framework does it this way because that's exactly what the developer wants 99.9% of the time. If you are going to use an entity object as an object that you want to move around and manipulate in ways other than treating it as a model of the database (like it should be), then you may want to consider creating another new wrapper class that lets you mess with all the data fields that you want (and have others that aren't in there), and then have the save method of it do the proper entity framework persistance, to keep things separate and clean.