I have a code block which checks whether an entity is being tracked by my context. If it is, I need to detach it. This works for a given T type.
public virtual async Task<bool> InsertOrUpdate(TE entity)
{
if (entity.Id == 0 || entity.Id == ModelState.New)
{
// attach new entity
_context.Entry(entity).State = EntityState.Added;
}
else
{
// Sometimes when you want to update a detached entity, before attempting to attach it (by setting the .State property),
// you first need to make sure the entity isn't already attached and being tracked. If this is the case, the existing entity
// needs to be detached, and the updated entity, attached.
var attachedEntity = _context.ChangeTracker.Entries<TE>().FirstOrDefault(e => e.Entity.Id == entity.Id);
if (attachedEntity != null)
{
// the entity you want to update is already attached, we need to detach it and attach the updated entity instead
_context.Entry<TE>(attachedEntity.Entity).State = EntityState.Detached;
}
_context.Entry<TE>(entity).State = EntityState.Modified; // Attach entity, and set State to Modified.
_context.Entry<TE>(entity).Property(o => o.CreatedUserId).IsModified = false;
_context.Entry<TE>(entity).Property(o => o.CreatedDate).IsModified = false;
}
return await _context.SaveChangesAsync() > 0;
}
I now need to change the method so that it fetches all objects of type IEntity within the given T entity parameter and then do the same logic for each object found, but I'm having trouble with setting the ChangeTracker.Entries as I need to set the T type to the current selected type within the foreach. I have no idea how to do this.
public virtual async Task<bool> InsertOrUpdate(TE entity)
{
//// Find all instances of IEntity within TE:
//// * IF entity is new we set State to EntityState.Added (INSERT)
//// * IF entity is existing, we set State to EntityState.Modified (UPDATE)
List<IEntity> found = FindAllInstances<IEntity>(entity);
foreach (IEntity ent in found)
{
if (entity.Id == 0 || entity.Id == ModelState.New)
{
// attach new entity
_context.Entry(entity).State = EntityState.Added;
}
else
{
// Sometimes when you want to update a detached entity, before attempting to attach it (by setting the .State property),
// you first need to make sure the entity isn't already attached and being tracked. If this is the case, the existing entity
// needs to be detached, and the updated entity, attached.
var attachedEntity = _context.ChangeTracker.Entries<TE>().FirstOrDefault(e => e.Entity.Id == entity.Id);
if (attachedEntity != null)
{
// the entity you want to update is already attached, we need to detach it and attach the updated entity instead
_context.Entry<TE>(attachedEntity.Entity).State = EntityState.Detached;
}
_context.Entry<TE>(entity).State = EntityState.Modified; // Attach entity, and set State to Modified.
_context.Entry<TE>(entity).Property(o => o.CreatedUserId).IsModified = false;
_context.Entry<TE>(entity).Property(o => o.CreatedDate).IsModified = false;
}
}
return await _context.SaveChangesAsync() > 0;
}
The AsNoTracking() extension method returns a new query and the returned entities will not be cached by the context (DbContext or Object Context). This means that the Entity Framework does not perform any additional processing or storage of the entities that are returned by the query.
Another way to get the EF version you are using is to open the Package Manager Console (PMC) in Visual Studio and type Get-Package at the prompt. The first line with be for EntityFramework and list the version the project has installed.
In Entity Framework, change tracking is enabled by default. You can also disable change tracking by setting the AutoDetectChangesEnabled property of DbContext to false. If this property is set to true then the Entity Framework maintains the state of entities.
AsNoTracking(IQueryable) Returns a new query where the entities returned will not be cached in the DbContext or ObjectContext. This method works by calling the AsNoTracking method of the underlying query object.
You could use the inner context wich is an ObjectContext.
var ctx = ((IObjectContextAdapter)_context).ObjectContext;
And then call ctx.Detach()
on whatever entity you want. Fortunately this is not a generic method.
You can also get a reference to an ObjetStateManager
from the ObjectContext
and use it to do whatever state change you want.
More informations: https://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.objectstatemanager(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.data.objects.objectstatemanager(v=vs.110).aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With