none
Remove entities from local and context without marking for deletion RRS feed

  • Question

  • All,

    Using EF 4.4 with ModelFirst design.  Is there a way, without creating a new DbContext, to clear the existing dbSet<T>.Local cache WITHOUT marking each item for deletion?  What I've been doing is

    dbSet<T>.Local.Clear(); dbSet<T>.Where(a => Entry(a).State == EntityState.Deleted).ToList().ForEach(a => Entry(a).State = EntityState.Detatched); 

    which kind of works, but then it gets messy if I need to call that data again.  The reason I don't want to initialize a new DbContext is because I have related data that is loaded (Eager Loading), and I don't want this data to change or to have to reload this context.

    What I'm looking for is something like dbSet<T>.local.Clear() that actually removes all entries and deletes them from the ChangeTracker as well, without posing back to the DB.

    Thanks.


    • Edited by whiteheadw Tuesday, October 30, 2012 10:44 PM
    Tuesday, October 30, 2012 10:44 PM

All replies

  • Hi Whiteheadw,

    Welcome to the MSDN forum.

    Please try this:

            static void Main(string[] args)
            {
                using (var context = new Entities())
                {
                    var results = context.CompanyProducts.Where(p => p.ID > 3).ToList();
                    Console.WriteLine(context.CompanyProducts.Local.Count);
                    RemoveEntities<CompanyProduct>(context);
                    Console.WriteLine(context.CompanyProducts.Local.Count);
    
                    Console.ReadLine();
                }
            }
            static void RemoveEntities<T>(Entities context) where T : class
            {
                context.Set<T>().Local.ToList().ForEach(p => context.Entry(p).State = EntityState.Detached);
            }

    After RemoveEntities method is called, the entity objects still exist in memory. If you want to use them again, please attach them again.

    Have a nice day.


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us

    Thursday, November 1, 2012 8:37 AM
  • Take a look at my code I posted in my question.  That's kind of what I've been doing.  In fact, I fail to see anything fundamentally different from what I've been doing and the code that you posted.  What I was looking for was something a little cleaner (if it exists), but I guess it doesn't.

    With that said, I've managed to simplify my logic when needed to call this data again so that it's about as clean as it's going to get.

    So, for now, when I need to clear cache, I set the entity to detached (which I've been doing, and which you recommended, nothing new here).  Next, I query the DB with new criteria (regardless of what is in detached state), and THEN look for detached entities in ChangeTracker.Entries<T>(). (since EF won't pull in these Entities if in DbContext in a Detatched State anyway).

    Since I also needed to know the state of the Entity before it went into a Detatched State, this also meant adding an internal EntityState OldEntityState{get;set;} property to all my entities (easy to do, since I modified my T4 template to make all entities inherit from a base class) to keep track of old entity states so I could easily reset an Entry<T>(T Entity).State to Entry<T>(T Entity).Entity.OldEntityState.

    Thus, my new code looks something like this:

            public void LoadWithNewCriteria(string NewFieldCriteria)
            {              
                if (MyEntitySet.Local.Any())
                    ChangeTracker.Entries<MyEntityType>().ToList().ForEach(a => { a.Entity.OldEntityState = a.State; a.State = EntityState.Detached; });
                MyEntitySet.Where(a => a.Field1 == NewFieldCriteria).Load();
                ChangeTracker.Entries<MyEntityType>().Where(a => a.Entity.Field1 == NewFieldCriteria && a.State == EntityState.Detatched).ToList().ForEach(a => a.State = a.Entity.OldEntityState);
            }

    Thursday, November 1, 2012 4:10 PM