views:

331

answers:

2

In the olden days of the DataSet (and related objects), the in-memory representations of the data objects--DataRow and DataRowView--supported transactional edits through BeginEdit, EndEdit, and CancelEdit. Having both in place allowed more than simply being able to "undo" changes made to an object and reverting it back to its retrieved (or uninitialized) values; the DataRowView object allowed a developer to begin a single editing operation on a DataRow in any state and undo those changes without undoing other changes that might have been made.

For example,

DataRow retrieved as:

Col1    | Col2
----------------
1         2

DataRow Modified to:

Col1    | Col2
----------------
1         3

BeginEdit called on a DataRowView object for this row.

DataRowView modified to:

Col1    | Col2
----------------
2         3

CancelEdit called on the DataRowView, reverting the values to

Col1    | Col2
----------------
1         3

So the change was undone, but the values present before the edit--even though they were in-memory changes and not the retrieved values--are preserved.

Is there any similar facility in the Entity Framework? I have a sneaking suspicion that the answer is "no", considering that it looks like an Entity uses simple backing variables for column values rather than a "property bag" approach like the DataRow uses (or WPF's DependencyProperty infrastructure uses).

A: 

There are two ways to do transactions with the Entity Framework, depending upon the depth of transactional support you need.

  1. The "right" way to do it is with a TransactionScope instance. The Entity Framework supports this. The downside of this method is that you are now in a distributed transaction, which has security implications for the connection between your machine and your database server.
  2. The "lite" way to do it is with the SaveOptions argument to SaveChanges. This allows you to keep change tracking information around after the call to SaveChanges, and "accept" the changes (save to the DB and dispose change tracking information) later.

Regarding your speculation in the last paragraph of the question: In EF 1, change tracking information was typically stored in the ObjectContext. In EF 4, you will have the option to use so-called "self-tracking" entities or proxies, which behave more in the manner you are expecting. But the default, I think, will still be to behave like EF 1. If you look at the generated C# code for your EDMX file, you will see how the property change notification works.

Craig Stuntz
Unless I'm misunderstanding your answer (and that's entirely possible), it sounds like you're talking about transactional *database operations*. While that's obviously important, that isn't what I'm going for here. All of what I'm talking about is client-side. See the `DataRow` and `DataRowView` implementations of `IEditableObject` and `ICancelEdit` for a better explanation.
Adam Robinson
No, I'm talking about distributed transactions, which include, but are *by no means limited to* database transactions. Read the link I gave you for TransactionScope.
Craig Stuntz
You're right, the `TransactionScope` object can be used for operations other than database operations, but I don't believe that it's applicable in this scenario. Again, all I'm talking about is an *in memory* change to the property values. I don't see how the `TransactionScope` can have any effect on those unless there is some serious magic going on that I'm not aware of.
Adam Robinson
A: 

You can implement IEditableObject on your entities.

See here for an example.

Andrew Peters
Have you personally used this (just curious)? I'm a little wary of a PostSharp solution...I've never been entirely comfortable with taking declarative programming to that level, but I may be a bit of a curmudgeon in that way.
Adam Robinson
Implementing it by hand is pretty straightforward. I would try that first.
Andrew Peters