Reputation: 39180
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
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 onIQueryable
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 theDbContext
in theUnchanged
stateThe
Local
property will give you anObservableCollection<TEntity>
that contains allUnchanged
,Modified
andAdded
objects that are currently tracked by theDbContext
for the givenDbSet
. As new objects enter theDbSet
(through queries,DbSet
.Add
/Attach
, etc.) they will appear in theObservableCollection
. When an object is deleted from the DbSet it will also be removed from theObservableCollection
. Adding or Removing from the ObservableCollection will also perform the correspondingAdd
/Remove
on theDbSet
. Because WPF natively supports binding to anObservableCollection
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