Rollingback vs Refreshing vs Reloading Entity data

2019-08-18 05:11发布

问题:

I have an WPF project, MVVM with an EF6 dataset and I'm looking to implement a way to rollback all changes.

The following code shows how ViewModel loads the data:

protected async override void GetData()
{
    ThrobberVisible = Visibility.Visible;

    ObservableCollection<MobileDeviceRequestVM> _requests = new ObservableCollection<MobileDeviceRequestVM>();

    var requests = await (from c in dbContext.MobileDeviceRequests
                           orderby c.RequestDate
                           select c)
                           .ToListAsync();

    foreach (MobileDeviceRequest req in requests)
    {
        _requests.Add(new MobileDeviceRequestVM { IsNew = false, TheEntity = req });
    }
    MobileDeviceRequests = _requests;
    RaisePropertyChanged("MobileDeviceRequests");
    ThrobberVisible = Visibility.Collapsed;
}

The following code shows how the ViewModel rolls back any changes:

protected override void RollbackData()
{
    var changedEntries = dbContext.ChangeTracker.Entries()
        .Where(x => x.State != EntityState.Unchanged).ToList();

    foreach (var entry in changedEntries)
    {
        switch (entry.State)
        {
            case EntityState.Modified:
                entry.CurrentValues.SetValues(entry.OriginalValues);
                entry.State = EntityState.Unchanged;
                break;
            case EntityState.Added:
                entry.State = EntityState.Detached;
                break;
            case EntityState.Deleted:
                entry.State = EntityState.Unchanged;
                break;
        }
    }

    //Somewhere in here the OC: MobileDeviceRequests needs to get refreshed
    //with the context as items may have been added and/or deleted

    RaisePropertyChanged("MobileDeviceRequests");
}

The following code shows how the ViewModel refreshes the data, which may or may not rollback data depending on if something has changed:

protected virtual void RefreshData()
{
    GetData();
}

The following creates a new context

protected virtual void ReloadData()
{
    dbContext= new BAContext();
    GetData();
}

What I'm wondering about is:
Rolling Back
vs
Refreshing
vs
Reloading

They all seem to do virtually the same thing, the ReloadData() being the more expensive.

I guess what I'm asking is, if refresh does the requery and populates the OC, is there any point in having a rollback. If there is, then how would you repopulate the OC and would it be any different than the refresh?

回答1:

The aforementioned methods are not equivalent.

When executing LINQ to Entities tracking query, EF will requery the database, but then will take into account the current change tracker state of the returned entities, and will return the local entity data rather than actual data. The concept is similar to the RefreshMode.ClientWins options of the older ObjectContext.Refresh method.

The net effect of your refresh will be that it eventually will bring the new data (added to the database through different context instance or another process/user). But the current modifications will stay in effect.

So IMO you the options are just two - rollback the current or use new context. The way you implemented it, rollback method seems to work, but entity queries still will not apply changes made outside the context instance. But this applies to the tracked entity queries in a long lived context anyway, so probably might not be considered a defect.

Which one of the two you choose depends on your requirements. But the only guaranteed way to start really fresh is to use a new context instance.