How to fix "EntityMemberChanged was called without first calling EntityMemberChanging" - entity-framework

This came up time and again for us. After reading such a message, there's nothing intuitive to do and debug.

What this poorly-documented error is trying to say is that you accidentally set up a system in which tracking changes causes more changes.
When Entity Framework changed a property on one of your entities, such as during SaveChanges with identity ID updates, you ran code that changed other tracked properties.
For example, the property that Entity Framework was setting triggered an event, perhaps INotifyPropertyChanged, which perhaps was subscribed to by a BindingSource or some binding list, whose ListChanged event handler was in the UI and triggered a calculation of some other property, and the change tracker detected the second property change.
The simple diagnosis is to place a breakpoint on the SaveChanges() call and immediately after the SaveChanges call(). When the first breakpoint is hit, place a breakpoint on each event handler that could possibly be triggered. (BindingSources are notorious for multiplying each other's events.) Continue debugging. If any breakpoint is hit other than the point immediately following SaveChanges, you know where the problem is.
The simple solution is to set a flag, such as IsSaving, on each side of the SaveChanges call. Then in each misbehaving event handler, do a simple check and do not modify any entities if the DbContext is in the process of saving. Make sure you use finally in case SaveChanges throws an exception that you catch at a higher level:
IsSaving = true;
try
{
await db.SaveChangesAsync()
}
finally
{
IsSaving = false;
}
(One other possibility is that you were changing the entity from multiple threads — never involve the change tracker in multiple threads!)

I had the exact same issue. I had wired to the INotifyPropertyChanged event that created the possibility for a property to change during the SaveChanges() call. I think it is a better practice to unwire the event handlers of you tracked entities when performing dbContext.SaveChanges(), Remove().

I'll explain my experience with this error, hoping it might help someone. And thanks to jnm2 for beautiful explanation.
I had Invoice and Receipt entities, and InvoiceViewModel.
Thie ViewModel was subscribed to Invoice property changed, inside which it was raising CanExecuteChanged events.
I added Receipt to Invoice navigation property and called SaveChanges(), which raised Invoice.ReceiptID property changed and triggered OnPropertyChanged event handler on the ViewModel, which in turn raised all kinds of CanExecuteChanged events.
The problem was that one of the CanCommandNameExecute methods was calling Context.ChangeTracker.HasChanges() which ultimately threw an exception.
How I fixed it?
I followed jnm2, I flagged VM with IsSaving and checked for the flag inside OnPropertyChanged event handler.
Once again, thanks jnm2, and hope someone finds this helpful as well.

Related

Entity Framework Core: SaveChanges() NON-async throws "A second operation was started on this context before a previous operation completed."

I am fairly new to Entity Framework and everything has been moving smoothly, until I encountered this error. My code is attempting to save children of a parent table using SaveChanges() but I get this error:
A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext.
This message seems tied to async calls and having to use await - SaveChangesAsync(). However I am NOT calling the async version of the SaveChanges() method but still get a thread error message.
My code is fairly simple:
public void CreateRange(IList<Section> sections)
{
// Add new sections and save context.
_SqlRunnerContext.sectionsDbSet.AddRange(sections);
_SqlRunnerContext.SaveChanges(); // This line throws the error.
}
The error seems to occur when there are at least two entries in the list. Which makes me think it's the way that Entity Framework is handling the save internally.
The code that calls this method creates a new repository which in turn creates a new dao and SqlContext. Given this I wouldn't think it would be something outside of this code causing the issue. I have also tried a foreach loop and save each item individually with the same error.
If anyone could give me a suggestion or idea what to try, it would be much appreciated.
Thanks again,
Adam
Instead of deleting all records then re-inserting. I change the code to simply update if it exists and add if new. This has resolved the issue.

How is the PropertyChanged event used

How is the PropertyChanged event used?
I'm wanting to evaluated the next state of a state machine whenever any property of the class is changed.
Regards Steve
PropertyChanged is part of the standard IPropertyNotifyChanged signaling.
If you want to create side effects if any change is done - consider setting "HasUserCode" on each attribute, Generate code, now you will find a partial method available for you to fill for Set and Get of attributes.
In a setter you can have side effects like running a trigger to step a state machine.

Doctrine 2, Need to execute code pre-persist/post-persist

I am using Doctrine 2 entities. We have some entities which have to update related items when they are saved to the database. For example, when a user record is modified, we save it as a new record, with the "inactive" field set to 'false'. However, we have to set the the 'inactive' field for all previous record for that user to 'true'. This is done to keep an audit history. It is a Legacy database, so changing the structure is not an option.
Since Doctrine saves objects by passing them to a persister object (persist::($thisObj)), rather than the object having a save method ($thisObj->save()), we can't just extend a 'save' method from a parent object. The only option I see here is to try to extend the 'persist' object, but that sounds like a goose gaggle, just waiting to happen.
I found some information on events, but do not see how to add them to make events fire a particular function when a particular entity is persisted.
How do I add pre-save/post-save functionality to some of my entities ?
So, you probably already know http://www.doctrine-project.org/docs/orm/2.1/en/reference/events.html right?
You add an annotation that the entity contains callbacks and then create specific functions (which need to be public) on that entity and also annotate them with #PrePersist or #PostPersist or whatever.
The other way is creating an event subscriber, register that one with the doctrine event manager and implement methods called prePersist, postPersist etc. They get passed an EventArguments object which contains the entity relevant for the occurred event.
I know this is a very general answer to your question, but you need to be a bit more specific where your problem lies.
Please dont exend the entity manager and overwrite the persist method, there are way cleaner methods for doing what you need as far as I can tell.
It's actually quite simple to do what you want to do. It does not require dorking with the event manager, or anything complex like that. You use something called "Lifecycle callbacks". These are functions that Doctrine automatically runs during the "lifecycle" of the entity, ie: prePersist, postPersist, preUpdate, postUpdate, etc. You can find the complete list here: http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html
The process of adding this functionality to your entities is very simple.
In the Annotations section of your entity, include the following tag: "#HasLifecycleCallbacks". This tells Doctrine that it should search the entity for functions to run upon various events
Write a public function in your entity that you would like to fire upon a specific event.
Put an annotation above the function indicating which event it should be used to handle.
For example, look at the following code:
/** #PostPersist */
public function doSPostPersist() {
$this->tester = 'Value changed by post-persist';
}
I have found that sometimes the events simply refuse to fire, and I don't yet know why. But when they do fire, they will fire reliably.
Don't forget to enable Lifecycle Callbacks in your class annotation :
/**
* Report\MainBundle\Entity\Serveur
* #ORM\HasLifecycleCallbacks
*/
class Serveur {

Business Logic when Saving in Entity Framework

If I want to perform some action when an entity is saved, I can do something as described here.
However, suppose I retrieve an object from the database. This object has a list of items within it. If I instantiate a new item and add it to this list and then save all changes, the item in the list is not part of the "GetObjectStateEntries".
The problem for my situation, I believe, has been resolved. There appears to be a bug, in my opinion, in the ObjectContext.SaveChanges(SaveOptions) method. Even though this method will call DetectChanges (depending on the saveOptions), the OnSavingChanges method is called FIRST. This, I think, is a problem.
The solution to this is to call ObjectContext.DetectChanges() prior to calling SaveChanges().

How to properly use Object Contexts in Entity Framework using BackgroundWorker

I am developing using Entity Framework and WPF, and I am encountering some errors and I don't know why. When saving a record (using a BackgroundWorker), I set the entities change tracker to nothing (null), attach the record to a new disposable context, save it, detach, and dispose of the context.
Saving a record fires and event in theMainViewModel of the program that the other ViewModels (including the one that is saving) need to refresh their entities to reflect changes.
Private Sub _saveRecordWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles _saveRecordWorker.DoWork
Using MyContext As New RVShippingEntities
Dim MyShipment = CType(ShipmentRecord, IEntityWithChangeTracker)
MyShipment.SetChangeTracker(Nothing)
MyContext.Attach(MyShipment)
MyContext.Detach(ShipmentRecord)
End Using
End Sub
The Refresh background worker is similar, but it has a Do While block to keep it from interfering with the save worker (which doesn't appear to be working; hence the post). When I save (and it subsequently refreshes) I get the following error:
The calling thread cannot access this object because a different thread owns it.
I thought that with theDoWhile block, it would wait (and when I step through it does) until the save thread finished, and all would be good. But it would seem that something (either the main thread or the save thread) is still doing something that is interfering.
Is there a better way of doing this? Am I doing it in a goofy kludgey fashion? Any help would be appreciated.
(Apparently Firefox recognized kludgey as a word. Interesting)
So, 3+ months and nary an exception so far in relation to Entity Framework. I am going to call this the answer.
Parent Views (in my case Company, Customer, Shipment) have a context which is passed to child Views as necessary (Addresses, Phone Nums, Email Addresses, for Company and Customer; Packages, Contents, for Shipments). Anytime a context can't save changes or what have you (db disconnection is most common cause), the context is disposed, a new one instanced, the entities are re-attached, set to modified (based on custom change tracking which I do for UI), and changes are saved.