Chuck B
Chuck B

Reputation: 51

Entity Framework 5 issue deleting - Object State Manager issue

I'm getting the following error when I try to delete an entity:

"An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key."

I have read the other posts here related to this error and have tried detaching the filter with no luck. maybe I'm missing something simple or should use a different approach to delete these filters(I already tried remove method)? Any help would be greatly appreciated.

Here's the code: I'm using ASP.NET 4.5 and EF 5. The simple repository class this is in has a private dbContext being initialized in the repository constructor and destroyed in the destructor.

namespace AuditLog.Repositories
{
    public class FilterSetRepository : IFilterSetRepository
    {
        private readonly AuditLogEntities _ctx;

        /// <summary>
        /// Default constructor
        /// </summary>
        public FilterSetRepository()
        {
            _ctx = new AuditLogEntities();
        }

        /// <summary>
        /// Destructor
        /// </summary>
        ~FilterSetRepository()
        {
            _ctx.Dispose();
        }

The error gets thrown on the line that has _ctx.Entry(filter).State = EntityState.Deleted; inside the foreach loop (below). The entity called FilterSet has a list of Filter entities that must be deleted from their table before I can delete a FilterSet. I can provide the class code showing them if necessary. Just above the offending line is where I tried the detach method, but it said it couldn't detach because a key wasn't already attached.

/// <summary>
/// Delete a particular filter set and its filters.
/// </summary>
/// <param name="filterSet">The filter set to be deleted.</param>
public void DeleteFilterSet(FilterSet filterSet)
{
    // First delete the child elements
    var filterRepository = new FilterRepository();
    foreach (var filter in filterRepository.GetFiltersBySets(filterSet))
    {
        _ctx.Entry(filter).State = EntityState.Deleted;
        _ctx.SaveChanges();
    }

    // ...then delete the filter set
    _ctx.Entry(filterSet).State = EntityState.Deleted;
    _ctx.SaveChanges();
}

Thank you in advance for your help!

Upvotes: 2

Views: 1484

Answers (3)

COLD TOLD
COLD TOLD

Reputation: 13569

_ctx.Entry(filter).State = EntityState.Deleted; does a lot of extra checking as it the state.

If you already have the filter object you might want to use:

_ctx.Attach(filter);
_ctx.Filter.Remove(filter);
_ctx.SaveChanges();

Upvotes: 1

Chuck B
Chuck B

Reputation: 51

After reading this post again I was able to modify my DeleteFilterSet code to find and handle the object whos key is already tracked by the Object State Manager. Here is the code that works:

/// <summary>
/// Delete a particular filter set and its filters.
/// </summary>
/// <param name="filterSet">The filter set to be deleted.</param>
public void DeleteFilterSet(FilterSet filterSet)
{
  // First delete the child elements
  var filterRepository = new FilterRepository();

  foreach (var filter in filterRepository.GetFiltersBySets(filterSet))
  {
      var entry = _ctx.Entry(filter);

      if (entry.State==EntityState.Detached)
      {
          var set = _ctx.Set<Filter>();
          Filter attachedEntity = set.Local.SingleOrDefault(e => e.FilterId == filter.FilterId);

          if (attachedEntity!=null)
          {
              var attachedEntry = _ctx.Entry(attachedEntity);
              attachedEntry.State=EntityState.Deleted;
          }
          else
          {
              entry.State = EntityState.Deleted;
          }
      }
       _ctx.SaveChanges();
  }

   // ...then delete the filter set
   _ctx.FilterSets.Remove(filterSet);
   _ctx.SaveChanges();
}

I hope this solution helps someone else.

Upvotes: 2

SHM
SHM

Reputation: 1952

i once had this exception and fixed it with this and it happens when you want to add an object to context (attach) and there is already another object with same primary key value in dbcontext. i suggest you add an Attach Method to your sql repository like this:

  public void Attach(T itemToBeAttached)
    {
        T old = _objectSet.Local.FirstOrDefault(i => i.Id == itemToBeAttached.Id);
        if (old != null)
        {
            _context.Entry<T>(old).State = EntityState.Detached;
        }
        _objectSet.Attach(itemToBeAttached);
    }

the key here is the load prperty of objectSet.

when you want to delete an entity and the entity dosnt exist in object context it first checks if the state of objects is attached and if its not attached then ef will attach to db thats where exceptin is thrown if another object already exists in context with same key.

Upvotes: 1

Related Questions