How to maintain data after DbSet.Remove? - c#

I use a repository pattern and to make things centralized I created a IValidate interface that each of my repositories can implement. In that I make entity validations depending on their state. So far so good, until I removed an entity. When I tried to access a property from a removed entity I got an exception, the entity was no longer in context.
Ex:
class A
{
int MyClassBId
B MyClassB
}
If I add or update entity A I can access A.MyClassB with no hassle. But if I delete (DbSet.Remove) even before calling SaveChanges (my approach of course calls this Validations before save) the references are null. So if I try to access A.MyClassB again I get null reference, but the "not lazy-loaded" objects are there. For instance, A.MyClassBId still has the FK for B.
I understood that DbSet.Remove only marked the entity for deletion, nothing else. Does it also remove it from context? How can I solve this? Call DbSet.Remove and still maintain the references in the object, at least until SaveChanges is called?
Thanks.

You have to understand that two processes are going on:
Entity Framework keeps track of the entities that are loaded in DbContext, maintaining their state as Added, Modified, Deleted or Unchanged. You can check this with a MyDataContext.Entry(MyEntity).Statecall.
Outwardly the POCO classes behave just like you would expect from classes that have no connection to an ORM whatsoever.
So what happens when you call the DbSet.Remove method is that the entity will be marked for deletion under the covers and outwardly it will be removed from the ICollection that it belonged too.
If you want to keep track of entities that should be deleted on a SaveChanges call you will have to define a WillBeDeleted property on the entity and your code will have to take this property into account when counting active entities, validation, etc. The actual DbSet.Remove call should then be made just before calling SaveChanges.
Alternatively, you can use MyDataContext.Configuration.AutoDetectChangesEnabled=False before initialising the DbContext. Now the Entity that is subjected to the DbSet.Remove method will not be deleted from its ICollection in the POCO class, but you have no way of knowing that the entity is meant to be deleted without again tracking this in a property of your own.

Related

Cannot use a Remove ⇒ AddOrUpdate sequence with Entity Framework

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).

How to make it explicit in Web API 2 for Entity Framework to only add parts of the object that have changed?

I'm using ASP.NET WebApi 2 and loading in part of a relational database structure into the front end website. This allows the user to make changes to multiple tables in a single store and to also view some extra data.
This mostly works pretty well. It means I can store changes to, say a person table and their related clothes and hair color on one call as follows:
db.person.Add(person);
db.SaveChanges();
The problem is that, I don't want to load all the related data. So where the shoe table may be loaded, I don't want the laces table to load with info about laces.
The issue I'm running into is that there is an attempt to store a duplicate shoe table to the database even though this was only loaded to allow the user to view these details. I imagine that this is because, I'm using [JsonIgnore] attributes to ignore certain parts of the object - it is thus recognizing this as a new object, when it isn't.
I could loop through the object removing any shoe information before call Add, but this would be slow.
Perhaps it is best to post a second object that only includes the items that have changed (after tracking these in the front end). Is there a better way?
When you use DbSet<T>.Add() in EF, the entity (or all the entitis in the tree, if it's an entity with related child entities) is attached to the DbContext as Added. That means that when you call SaveChanges EF will try to insert all the objects in the database. That's why you're getting duplication problems.
You need to learn how to work in disconnected mode with EF. Basically you need to track the state of each entity (i.e. control if they have to be inserted, deleted or updated), and set the correct state when you attach the entities in the context.
Look for docs on working with disconnected entities in EF, for example:
Persistence in Entity Framework
Add, Attach and Entity States
These will explain you how to handle disconnected entities.

Nhibernate unit of work and automatic saving

I'm implemented the unit of work like this tutorial explained:
http://www.codeproject.com/Articles/543810/Dependency-Injection-and-Unit-Of-Work-using-Castle
Though now I encounter a strange problem.
I load within a unit of work (in the transaction) an entity from the database
I update a property of that entity
I call not the save method on my repository
The transaction is committed
In this scenario, I would expect that the updated property is not persisted to the database. But it is. So an entity loaded in my session is tracked and committed to the database without calling save. What is causing this? And is there a way to tell Nhibernate not to update those entities if the save is not called?
I realize I can work around this to update only a property when I need to update. The only risk is by accident updating the property by mistake and it is then very hard to find this problem. (and for example someone new, not knowing this could easily make a mistake)
The explanation requires understanding the difference between a transient and a persistent entity. A transient entity is a new entity and it is made persistent by calling Save(). An entity that has been retrieved using NHibernate is already persistent and any changes made to it will be automatically saved when the session is flushed. NHibernate's goal is to make the database consistent with the domain model when the session ends.
See chapter 9 in the documentation.

Generic method for comparing 2 objects and update changes from one to the other in c#

Problem case:
My problem is editing disconnected POCO entities and then saving them to the database (Uisng Entity Framework). When doing so, the generated sql updates ALL properties even though only some have actually changed. When I do the same within the context, the generated sql correctly updates only the modified properties. This causes problem with my auditing code since it wrongly stores changes on all the properties. This is made worst when the entity I am persisting has a complicated model with many relationships.
My proposed solution:
Instead of attaching the modified entity to the context, I want to query the entity and then manually syncronize the two object with a generic method that will work for any model. So I need to compare all properties from each object and update the modified properties to the attached entity. How do I go about updating the values in the properties, keeping in mind that changes might include new or modified relationships ?
Any thoughts?

How do I prevent an object from being persisted using Entity Framework Code First?

I've an object model I'm persisting to a SQL Compact database using EF 4.2. One of my classes has a flag I use to determine if the object was modified. If the object was never changed from its default value I do not wish to save it to the database. Is there a way I can configure DbModelBuilder to toss out objects based on this property (it's a bool)? The other option I am considering is overriding DbContext.SaveChanges and just removing the object from the DbSet if the object was not modified. Suggestions?
If the attached object was not modified it will not be saved to database. DbContext has its own change tracking mechanism and it will not use your custom property.
Why not add this to your business logic? What I mean is, why should EF deal with this? It could be as simple as:
if myObj.WasModified
context.SaveChanges()
else
do nothing
Not to mention EF won't do anything if the object wasn't modified anyway

Categories