hibernate envers: get modified entities for current revision - hibernate-envers

In the current transaction, before committing, I want to see all changes for the current revision. I can get the current revision by doing :
auditReader.GetCurrentRevision<CustomRevisionEntity>(true)
The modifiedBy and revision number are correct. However the ModifiedEntityNames is null, although some entities were modified within this transaction. ModifiedEntityNames is the property that maps to the ENTITYNAME column of the REVCHANGES table
The below code returns an empty set:
ISet<Tuple<string, Type>> modifiedEntityTypes = auditReader.CrossTypeRevisionChangesReader().FindEntityTypes(lastRevision.Value);
Is it not possible to retrieve modified entities before committing ?

At least in the Java version, changes are written on a commit/flush.

Related

#Version annotation in spring

Hey guys how can I use #version annotation but instead of replacing the modified data add a new row with the same identifier and the incremented version in the database.
For example here the id 173 is duplicated the only change is the version, that's my goal.
enter image description here
#Version is intended for optimistic locking and should not be used for this.
As Taylor commented you can use Hibernate Envers for something really similar. It will result in a separate table containing all your versions, while the main table that you map your entity to still has only the current version.
If you want all these entities to be actually in the same table you should just make the existing id plus an additional version field the id and then copy the entity and update the version before changing it. Version field here means a normal probably numeric field that you use as version it must not be annotated with #Version.
If you really want to abuse the #Version attribute you could create a trigger on the underlying table that creates a new row on every update.

spring data - read only entity based on view - how to get up-to-date data?

I built a jpa-entity on top of a database view.
The #Version field is mapped to the revision of the table the view is set up upon.
However, when the underlying table row changes, I do net get the update in my view-entity.
When I select the table row directly, I see that its revision changed.
How can I force two request against an entity based on an sql-view to use the latest data and not a cached state?
It turned out my problem occurs only in test ... when I read-modify-read an entity in the same test method, I have to manually refresh it in between, when I do a rest itest against the application, the latest values are returned ... so nothing to do here

Entity Framework Core updating unchanged fields

I'm not sure if this is a question about Entity Framework, or how the audit.net library works, but I was guessing it was with how I was performing updates with EF. My goal is to capture only actual changes to the record, but it's capturing everything as change, even if the old and new values are identical.
Basically to simplify it as much as possible, if I do
var existing = context.Appl.FirstOrDefault(a => a.Id == id);
context.Appl.Update(existing);
context.SaveChanges();
(Changing nothing)
The Audit.Net change log says every single field was changed, and looks like
"Changes": [
{
"ColumnName": "FOO",
"OriginalValue": "",
"NewValue": ""
},
..... many more
My goal is to capture only actual changes to the record
Then you should not use the Update method.
According to the Update method documentation:
Begins tracking the given entity in the Modified state such that it will be updated in the database when SaveChanges() is called.
All properties of the entity will be marked as modified. To mark only some properties as modified, use Attach(Object) to begin tracking the entity in the Unchanged state and then use the returned EntityEntry to mark the desired properties as modified.
The main usage case for Update method is to perform a so called forced update when working with Disconnected Entities. Since your existing entity is retrieved from the context (or in other words, is tracked by the context), hence all you need is to set the new values. Change tracker will detect if there are actual property changes and will issue UPDATE command with only modified values (or no UPDATE command at all if all current values are equal to the original values).

SaveChangesAsync fails and callback not executed (IdeaBlade)

I inherited an application built on Silverlight 4 using IdeaBlade from DevForce 2010 version 6.1.15.0. The backend database is SQL Server 2008. In tracking down some updates/inserts that weren't working, I discovered that I was getting the following error from the call to IdeaBlade.EntityModel.EntityManager.SaveChangesAsync().
"An entity or entities containing a referenced temporary Id is missing from the list of entities provided. Missing entities include: Revision: -100. See exception members for more details"
Additional digging uncovered the following additional information.
"The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_valuation_revision". The conflict occurred in database "XX", table "Revision", column 'RevisionID'. The statement has been terminated."
In digging deeper, I discovered the following:
The two main classes involved are: Valuation and Revision
Valuation has a collection of Revisions. On the database, this is represented by a FK on the Revision table (not null) that references the PK of the Valuation table.
In addition, Valuation has a reference to the CurrentRevision. This is represented on the database as a FK on the Valuation table (can be null if there are no revisions) that references the PK on the Revision table.
In the problem code, a new Revision object is created like so:
myNewRevision = new Revision { Valuation = myExistingValuation };
At this point, myNewRevision is an IdeaBlade.EntityModel.Entity with an EntityState of "Added".
After a couple of additional changes to the object, the following code is executed.
EntityManager.AddEntity(myNewRevision);
The above call to AddEntity doesn't seem to accomplish anything as the state of MyNewRevision is the same after the call as it is before the call.
Next an attempt is made to save the newly created Revision object.
SaveChangesAsync(new[] { myNewRevision }, null, RevisionCallback, null);
The above statement is within a try...catch block and no error is thrown, but the RevisionCallback routine is never executed. Also the EntityState of myNewRevision is still "Added" and the key is still showing as -100.
Then the existing Valuation object is updated with the reference to the new Revision.
myExistingValuation.CurrentRevision = myNewRevision;
This causes the EntityState of myExistingValuation to change from "Unchanged" to "Modified".
Finally, the code tries to save the changes to the Valuation object.
SaveChangesAsync(new[] { myExistingValuation }, null, ValuationCallback, null);
The result of this call is that the ValuationCallback is called, but myExistingValuation is still showing as "Modified", the reference to myExistingValuation.CurrentRevision still refers to myNewRevision with a key of -100 and an EntityState of "Added". The EntitySaveOperation object returned to the callback method has Exception == null, HasError = true, and the error is the one described at the beginning of this question. That is,
"An entity or entities containing a referenced temporary Id is missing from the list of entities provided. Missing entities include: Revision: -100. See exception members for more details"
and
"The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_valuation_revision". The conflict occurred in database "XX", table "Revision", column 'RevisionID'. The statement has been terminated."
The database is not updated.
Any suggestions? Why doesn't the callback routine from the first call to SaveChangesAsync get executed? How can I get the updates to work?
It's odd that the RevisionCallback isn't called, but it's possible the async method hasn't completed when you do the next steps.
You can't use try/catch with the async methods here, as DevForce 2010 doesn't use the newer task-based async pattern; so exceptions will be returned to your callback or completion handler, or possibly to an EntityServerError handler if one is set up for the EntityManager.
DevForce will by default save all changes to entities in cache unless you specify a save list, but that list doesn't have to contain only one item. When you do a save of entities with temporary ids, all entities with a temporary PK or FK need to be in the save list passed to SaveChangesAsync. DevForce will automatically handle the fixup to the FK after the save completes successfully.
Is there any reason you can't do something like the following instead:
myNewRevision = new Revision { Valuation = myExistingValuation };
myExistingValuation.CurrentRevision = myNewRevision;
SaveChangesAsync(ValuationCallback);

Cannot add Currency field to Entity after Importing

A custom entity was created in our DEV environment. It originally had a Currency field, but we decided to remove it and use a Float field for simplicity. After exporting the solution and importing it into QA for the first time, I can no longer add a Currency field to the entity in QA (and the "leftover" transactioncurrencyid column in DEV did not get migrated to QA).
The main problem is that I cannot remove the transactioncurrencyid column and now my Filtered views are different between DEV and QA which causes our SharePoint BCS process that relies on Entity Framework to fail.
Is there any way to completely remove a currency field without recreating the entity?
Plan B: Is there a way to restore a past copy of the entity (prior to removing the currency) from a backup and merge it into our presently broken version?
Plan C: any other ideas (convert EF to use Stored Procs, etc)?
Thanks!
Export the entity from Dev into QA again. CRM will see that a column has been added, and will add it to the entity in QA.
Edit 1
So this is an unmanaged solution in QA? You should be able to just add the field to the entity in QA through the Customize Solution interface.
The MSFT approved solution involved manually removing:
the ExchangeRate column from the Base table (e.g. alter...drop column exchangerate)
the rows referencing the attribute's GUID in the system tables: Attribute, localizedlabel, AttributeIds (e.g. delete from tbl where AttributeId = guid)
altering the entity's View to remove the ExchangeRate column (not the Filtered)
Finding the GUID in Step 2 was done by opening the ExchangeRate field in CRM and pressing F11 to extract the AttributeID from the querystring.