Konrad Viltersten
Konrad Viltersten

Reputation: 39180

Not able to remove items from database when user deletes a row in data grid

When a user hits the button, I'm executing the following code.

using (Context context = new Context())
{
  foreach (Thing thing ViewModel.Things)
    context.Things.AddOrUpdate(thing);
  context.SaveChanges();
}

The updates are executed except for when the user selected a row and hit delete button. Visually, that post is gone but it's not really being removed from the database because it's not in the view model anymore. Hence, the loppification only ticks for the remaining things and not touching the removees.

I can think of two ways to handle that. One really bad - to remove everything from the context, save it and then recreate based on the view model. It's an idiotic solution so I'm only mentioning it for the reference's sake.

The other is to store each removed post in an array. Then, when the user invokes the code above, I could additionally perform the deletion of the elements in that array. This solution requires me to build the logic for that and I'm having this sense that it should be done automagically for me, if I ask nicely.

Am I right in my expectation and if so, how should I do it? If not, is there a smarter way to achieve my goal than creating this kill squad array?

At the moment, I do a double loop, first adding and updating what's left in the data grid. Then, removing anything that isn't found there. It's going to be painful if the number of elements grows. Also, for some reason I couldn't use Where because I need to rely on Contains and EF didn't let me do that. Not sure why.

using (Context context = new Context())
{
  foreach (Thing thing in ViewModel.Things)
    context.Things.AddOrUpdate(driver);
  foreach (Thing thing in context.Things)
    if (!ViewModel.Things.Contains(thing))
      context.Things.Remove(thing);
  context.SaveChanges();
}

Upvotes: 0

Views: 431

Answers (1)

ocuenca
ocuenca

Reputation: 39346

The first thing I want to advice you is you should use the AddOrUpdate extension method only for seeding migrations. The job of AddOrUpdate is to ensure that you don’t create duplicates when you seed data during development.


The best way to achieve what you need you can find it in this link.

First in your ViewModel class you should have an ObservableCollection property of type Thing:

public ObservableCollection<Thing> Things {get;set;}

Then in the ViewModel's constructor (or in another place), you should set the Things property this way:

context.Things.Load(); 
Things = context.Things.Local; 

From the quoted link:

Load is a new extension method on IQueryable that will cause the results of the query to be iterated, in EF this equates to materializing the results as objects and adding them to the DbContext in the Unchanged state

The Local property will give you an ObservableCollection<TEntity> that contains all Unchanged, Modified and Added objects that are currently tracked by the DbContext for the given DbSet. As new objects enter the DbSet (through queries, DbSet.Add/Attach, etc.) they will appear in the ObservableCollection. When an object is deleted from the DbSet it will also be removed from the ObservableCollection. Adding or Removing from the ObservableCollection will also perform the corresponding Add/Remove on the DbSet. Because WPF natively supports binding to an ObservableCollection there is no additional code required to have two way data binding with full support for WPF sorting, filtering etc.

Now to save changes, the only you need to do is create a command in your ViewModel class that call SaveThingsChanges method:

private void SaveThingsChanges()
{
   context.SaveChanges(); 
} 

Upvotes: 4

Related Questions