views:

2778

answers:

6

On Linq to SQL's DataContext I am able to call SubmitChanges() to submit all changes.

What I want is to somehow reject all changes in the datacontext and rollback all changes (preferable without going to the database).

Is this possible?

+8  A: 

Why not discard the data context and simply replace it with a new instance?

Haacked
Because I might have objects fetched through the context, which I might want to change/use at a later time.If I discard the data context I have to fetch those objects again.This is a windows service, where the datacontext live for a long time.
Thomas Jespersen
Also, what if your website is read only (yes those exist)
borisCallens
+2  A: 

The Refresh will work, however you have to give the entities you want to reset.

For example

dataContext.Refresh(RefreshMode.OverwriteCurrentValues, someObject);
David Basarab
this will however hit the database to get the most recent values, it doens't just revert to the old cached values.
Lucas
+2  A: 

As Haacked said, just drop the data context.

You probably shouldn't keep the data context alive for a long time. They're designed to be used in a transactional manner (i.e. one data context per atomic work unit). If you keep a data context alive for a long time, you run a greater risk of generating a concurrency exception when you update a stale entity.

Richard Poole
+3  A: 

Use the db.GetChangeSet().Updates.Clear() for updated, db.GetChangeSet().Inserts.Clear() for new or db.GetChangeSet().Deletes.Clear() for deleted items.

Shurup
This was the accepted answer? This doesn't work -- the Updates/Inserts/Deletes collections are read-only. And the MSDN documentation says that these collections are "computed at the time of the call" (of GetChangeSet()).http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.getchangeset.aspx
shaunmartin
We use this way to rollback in our projects and it works.
Shurup
Does not work for me (VS2008) -- I get exceptions "collection is read-only". But putting it into foreach loop and refreshing each table which is in ChangeSet -- works.
macias
+1  A: 

You can use the GetOriginalEntityState(..) to get the original values for the objects e.g. Customers using the old cached values.

You can also iterate through the changes e.g. updates and refresh the specific objects only and not the entire tables because the performance penalty will be high.

foreach (Customer c in MyDBContext.GetChangeSet().Updates)
        {
            MyDBContext.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, c);
        }

this will revert the changes using persisted data in the database.

Another solution is to dump the datacontext you use, using Dispose().

In any case it is a good practice to override the Insert and Remove methods in the collection of e.g. Customers you use and add e.g. an InsertOnSubmit() call. This will resolve your issue with pending Insertions and Deletions.

Theo Zographos
+3  A: 

Calling Clear() on the Updates, Deletes and Inserts collection does not work.

GetOriginalEntityState() can be useful, but it only gives the IDs for foreign key relationships, not the actual entities so you're left with a detached object.

Here's an article that explains how to discard changes from the data context: http://graemehill.ca/discard-changes-in-linq-to-sql-datacontext

EDIT: Calling Refresh() will undo updates, but not deletes and inserts.

Graeme Hill