views:

365

answers:

2

I would like to discard all changes made to linq tables (this means -- I use linq, and data are changed on client side, the data on server are intact). How to do this?

EDIT: problem partially solved

http://graemehill.ca/discard-changes-in-linq-to-sql-datacontext/

It works as long as you don't use transaction. When you do and you use mixed "mode" for a record, there is a problem:

begin trans
insert a record
update inserted record
commit trans

When you update record as above Linq counts it as updated record, and in case of exception you have two actions -- transaction is rolled back and data on Linq side are discarded. On discard changes Linq tries to fetch it from the database (discard for update means refetching data for a record), but since all changes were rolled back, there is no records for update.

The question

How to improve DiscardChanges method in a smart general way to work with transactions. Or how to change the workflow of transactions/discard-submitchanges to make all those work together?

Those are not smart solutions:

  1. refetching all data
  2. recreating connection to DB (because it leads to (1))
+2  A: 

Simply discard the current DataContext without calling SubmitChanges() and get a new one.

Example:

DataContext myOldDc = new DataContext();
Johannes Rudolph
There is 1 problem with this and 2 issues. Let's start from issues:a) efficiency -- I have to specify connection string for new data context, and it means it actually connects to the database again -- and this is not for freeb) side effects -- C# GC is not deterministic, which means old data context can still live, I am not sure what effect it would have with transactionsAnd the problem:a) I already passed the data context to several helper classes, when I change the data context I am doing it locally, and the helper classes when doing Submit they submit data I wanted to get rid off
macias
Don't assume that resubmitting the connection string will actually create a new connection unless you've verified that through Reflector. The connstring could just as easily be a key to a dictionary of connection pools, e.g.
Greg D
+2  A: 

To add to what Johannes said, I think the confusion here stems from thinking of the DataContext as something similar to a DataSet. It isn't.

A "table" in a DataContext is like a hint on how to retrieve a specific type of data entity from the database. Unlike a DataSet, the DataContext does not actually "contain" data, it simply tracks the discrete entities you've pulled out of it. If the DataContext disappears (is disposed), the entities are still valid, they are simply detached. This is different from a DataSet where the individual DataTables and DataRows are essentially bound to their containers and cannot outlive them.

In order to use the Refresh method of a DataContext, you need to use it on an actual entity or collection of entities. You can't "Refresh" a Table<T> because it's not actually a physical table, it's just a kind of reference.

Changes to entities connected to a DataContext are only persisted when you call the SubmitChanges method. If you dispose of the DataContext, there is absolutely no way that the changes can persist unless you manually reattach the detached entities to a new DataContext.

Aaronaught
+1: This can be surprisingly tricky to get right. I was once building a Linq to Sql app and I mentally "knew" this, yet I still painted myself into a corner when trying to create a good user experience in data entry dialogs that allowed the user to cancel changes. I like the ideas behind Linq to Sql, but I'm not sold on the execution in part because of the difficulty of doing this sort of task.
Greg D