Cannot use a Remove ⇒ AddOrUpdate sequence with Entity Framework - c#

I have a method that will Remove a set of entities.
I have a method that will AddOrUpdate a set of entities.
These methods are independently useful, but they have issues working together in entity framework.
The problem is that after removing a set of entities, for example (A,B,C,D), subsequent queries that resolve to one or more of those records always return cached garbage copies whose property values were nulled during the removal process. An intermediate DbContext.SaveChanges solves the issue, but introduces additional overhead and leaves the operation in a half-complete state, so it would also have to be wrapped in another transaction.
What's the best way to handle this.
Should I avoid an API that has Remove and Add/Update operations altogether, instead opting for an up-front hybrid operation that determines which ones are actually being removed and which ones are sticking around to be updated? or
Should I keep the two useful methods and just wrap the two steps in a transaction scope, so that I can save changes to the context immediately after the remove, allowing subsequent adds/updates to properly reflect their removal, while still have the ability to commit or rollback at the end (e.g. if the new permissions can/cannot be set)?
I don't want use lower-level operations such as turning off tracking or attaching/detaching entities.
Suppose the entities are permissions. Business logic dictates that I should use a logical two-step process to reset a user's permissions by first deleting any that I have permission to delete, followed immediately by trying to add/update any new permissions that I am allowed to assign.
When approaching this with two separate steps, I run into the problem as follows. The first problem I encounter is that immediately after removing a set of permission entities like (A,B,C,D), entity framework mangles the object properties, setting many of them to null (presumably to sever foreign key relationships). The problem is that because the entities still exist in the database, when trying to "add or update" a permission which still has a record in the database but has been removed in the context, EF always returns the cached/garbage copy of it. So although I've removed the entity... I can't actually determine, within that same context, whether I need to re-attach/update it or add a new entity outright. In other words, the framework returns an entity as though it exists (because it does still exist in the database) in spite of it being flagged as removed, but that entity object has garbage/null data, so that I can't even tell at that point whether it's safe to add a new one or I should try to "un-remove" the existing one.
It seems to me that such a remove/add-or-update pattern is simply not good for this kind of entity framework (or even ORMs in general). Instead, I'd have to determine, in a single up-front operation, whether any of the new permissions already exist, so I can selectively delete the ones that are going away, while updating the ones that are just being reassigned (a new access level, for example).

Related

EntityFrameworkCore AddOrUpdate

I want to add or update entities in EFCore 5.
Currently I am using Context.Find to determine whether to update or to add. I want this logic to be very performant and I see that much of cpu time is spent on the Find method (database call). I would like to move the logic of determining add or update to be evaluated by the database once SaveChanges is called. I would like to be able to specify which properties have changed and which should be used by the possibly already existing entity (or initialized with default values). I guess this can be done with Context.Entry(...).Property(...).IsModified.
I still want to be able to use the DbContext change tracking, multiple add or update calls should be combined, custom queries are not possible.
Primary keys are defined and not auto generated.
Is there any way to achieve this with EntityFrameworkCore?
There is/was IDbSetExtensions.AddOrUpdate but I think it is not available in current release? Also I think it is not recommended to use outside of migrations/seeding. Moreover I think it does not work as I guess it would overwrite existing values with default values of the changed entity (unchanged values should not be overwritten to default values, I am not recreating the complete entity on upsert, thats why I would like to specify which properties have changed).

What is the best way to ensure there is only a single ORM model instance tied to a row in a database?

The Problem
We have an app that stores hierarchical data in a database. We have defined a POCO object which represents a row of data.
The problem is we need certain properties to be dependent on the item's children and others on their ancestors. As an example, if a ((great)grand)child has incomplete state, then implicitly all of its parents are also incomplete. Similarly, if a parent has a status of disabled, then all children should be implicitly disabled as well.
On the database side of things, everything works thanks to triggers. However, the issue we're having is then synching those changes to any in-memory ORM objects that may have been affected.
That's why we're thinking to do all of this, we need to ensure there is only ever one model instance in memory for any specific row in the database. That's the crux of the entire problem.
We're currently doing that with triggers in the DB, and one giant hash-set of weak references to the objects keyed on the database's ID for the in-memory ORM objects, but we're not sure that's the proper way to go.
Initial Design
Our 'rookie' design started by loading all objects from the database which quickly blew out the memory, let alone took a lot of time loading data that may never actually be displayed in the UI as the user may never navigate to it.
Attempt 2
Our next attempt expanded on the former by dynamically loading only the levels needed for actual display in the UI, which greatly sped up loading, but now doesn't allow the state of the hierarchy to be polled without several calls to the database.
Attempt 2B
Similar to above, but we added persistent 'implicit status' fields which were updated via triggers in the database. That way if a parent was disabled, a trigger updated all children accordingly. Then the model objects simply refreshed themselves with the latest values from the database. This has the down-side of putting some business logic in the model layer and some in the database triggers as well as making both database writes and reads needed for every operation.
Fully Dynamic
This time we tried to make our models 'dumb' and removed our business layer completely from the code, moving that logic entirely to the database. That way there was only single-ownership of the business rules. Plus, this guaranteed bad data couldn't be inserted into the database in the first place. However, here too we needed to constantly poll the database for the 'current' values, meaning some logic did have to be built in to know which objects needed to be refreshed.
Fully Dynamic with Metadata
Similar to above, but all write calls to the database returned an update token that told the models if they had to refresh any loaded parents or children.
I'm hoping to get some feedback from the SO community on how to solve this issue.

Grouping changes to save in Entity Framework Core

Im running a process that will affect a lot of records within a database for a user. I only want to apply all of the changes or none of them depending on the result of all of the changes. (e.g if one of the sub processes fail then no changes overall should take place). I also want to save notifications to the database to alert users of the outcome of the processes (e.g if a sub process fails then a notification is raised to let the user know that no changes were made due to reason x).
The best way I can think to do this is to detach all of the entries within the change tracker as they are added, then create notifications if something has succeeded or failed and save changes, then when it comes to applying all the changes I can iterate though the change tracker and reset the Entity State and save changes once more.
The issue i'm facing with this approach is that when it comes to reset the Entity State, I don't know whether the entity is Added or Modified. I could implement my own change tracker to store the previous state of the entity but it would make EF's change tracker redundant.
I could also only add all of the entity's right when I come to save them but that would require passing many objects down a chain link of nested methods right until the end.
Does anyone have any better suggestions or is it standard practice to use one of the mentioned hacks for this problem?
It sounds like you are trying to implement the Unit of Work pattern. The DbContext of EntityFramework makes this fairly easy to use, as the DbContext its self is the unit of work.
Just instantiate a new context and make the changes you need to it. You can pass the context around to any functions that make their changes. Once the "logical unit" operations are complete, call SaveChanges. As long as the individual methods do not call SaveChanges, you can compose them together in to a single unit, committed once the entire logical operation as finished. Everything will be committed atomically, within a single transaction. The data won't be left in an inconsistent state.
You told about transactions. Using Transactions or SaveChanges(false) and AcceptAllChanges()?
also you can implement versions of data in DB. as for me it will be more ease and correct way (you must always only insert data and never update. 1-to-many). in this case you can simply delete last records or mark them as unactive

Entity Framework: SaveOptions.AcceptAllChangesAfterSave vs SaveOptions.DetectChangesBeforeSave

What is the difference between SaveOptions.AcceptAllChangesAfterSave and SaveOptions.DetectChangesBeforeSave in Entity Framework? When to use SaveOptions.None?
These options are provided in objectContext.SaveChanges(SaveOptions options).
Can any of these option, in any way, be used to reverse the changes made by objectContext.SaveChanges()?
They're two entirely different things. Note how SaveOptions has the Flags attribute: this indicates you can combine multiple flags, in this case to make SaveOptions.AcceptAllChangesAfterSave | SaveOptions.DetectChangesBeforeSave.
And if you're wondering about something like SaveOptions.None | SaveOptions.AcceptAllChangesAfterSave, then keep in mind that SaveOptions.None is the zero value, so this is just a long-winded way of writing SaveOptions.AcceptAllChangesAfterSave.
So you use SaveOptions.None when you want neither SaveOptions.AcceptAllChangesAfterSave nor SaveOptions.DetectChangesBeforeSave.
Can any of these option, in any way, be used to reverse the changes made by objectContext.SaveChanges()?
In the context? If you don't include SaveOptions.AcceptAllChangesAfterSave, then all changes will be preserved locally as unsaved. All added entities will remain in "added" state, all modified entities will remain in "modified" state, all deleted entities will still be available by explicitly requesting your context's deleted entities. Attempting to save again will likely fail, as the database has already been updated. You can then use the regular methods for reverting unsaved changes, but it requires a lot of manual work on your part, it requires manually looking up the original values of all properties and restoring that value. A detailed example of how to do this is, I think, beyond the scope of this question, but see Undo changes in entity framework entities.
In the database? This requires even more work on your part, and may not even be possible at all: once an entity with a server-generated column (e.g. auto-increment key, or row version field), it is generally impossible to restore it with those exact same values it originally had.

Linq to Entity AcceptAllChanges SaveChanges

What is the difference between the following:
db.AcceptAllChanges();
// vs
db.SaveChanges();
db.AddToCustomer()
// vs
db.Customers.AddObject(Mycustomer);
and why there is db.Customers.DeleteObject(Mycustomer); and no db.DeleteFromCustomer(Mycustomer);
when should i use each one ?
also is entity framework threadsafe ? i mean if two threads update the object in the context sametime would it crash ?
thanks in advance
db.AcceptAllChanges() assumes you have finished with any associated change history and discards it - if you have any further problems you cannot recover those changes. db.SaveChanges(false) does keep those changes in memory in case there are problems.
See http://blogs.msdn.com/b/alexj/archive/2009/01/11/savechanges-false.aspx for a more in depth answer.
db.AddToCustomer() is a strongly typed wrapper around db.Customers.AddObject(). Look at the definition of it and you'll see what I mean. I would use the db.AddToCustomer() method purely as it is strongly typed and gives you compile time type checking.
I imagine the only reason why there's no DeleteFromCustomer() is that they didn't think the work would be necessary (people tend to add more than they delete). There's nothing to stop you creating your own extension methods to implement it yourself however.
The EF is not thread safe, if you want to perform updates you'll need to manage the locking yourself. See http://blog.cincura.net/230902-multithreading-with-entity-framework/ for more :)
AcceptAllChanges only sets all added and modified entities in ObjectContextStateManager instance to Unchanged state and detach all deleted entities but it didn't execute changes in database. SaveChanges executes changes in database and by default also accept changes (can be configured not to do it).
AddToCustomer is the same as Customers.AddObject - it is just a shortcut (same with DeleteObject). The first method is generated by code generator (and I think it calls the second one which is standard method of ObjectSet).
Entity framework is not thread safe. Moreover you should be very careful when sharing ObjectContext among several threads.

Categories