# Client-Side Transactions

## Content

**DataSource for Entity Framework** gives developers a powerful mechanism for canceling changes on the client without involving the server. It is called *transaction* because it is similar to the common concept of database transaction in that it allows you to ensure that a certain group of changes (unit of work) is either made in its entirety or canceled in its entirety-that your code never makes incomplete or inconsistent changes to entities in memory. It is important to understand that these transactions have no affect in any way and are completely independent from database transactions. To distinguish them from database transactions, we sometimes call them *client-side transactions*.

Client-side transactions are especially useful in implementing **Cancel/Undo** buttons/commands. Doing this without [C1DataSource](/componentone/api/win/online-datasource/dotnet-framework-api/C1.Win.Data.Entity.4.8/C1.Win.Data.Entities.C1DataSource.html) requires cancelling all changes in the object context. [C1DataSource](/componentone/api/win/online-datasource/dotnet-framework-api/C1.Win.Data.Entity.4.8/C1.Win.Data.Entities.C1DataSource.html) client-side transactions make partial canceling of changes possible. And the transactions can even be nested, so you can have, for example, a dialog box with a **Cancel** button (which cancels only the changes made in that dialog box, not all changes in the object context made elsewhere in the application), and from that dialog box you can open another dialog box with its own **Cancel** button. Using a nested (child) transaction in the child dialog ensures that its **Cancel** button cancels (rolls back) only the changes made in the child dialog box, so the user can return to editing data in the parent dialog box and then accept or cancel changes in it using the parent transaction.

The easiest way to work with client-side transactions is by associating them with live views. For example, if we have a data grid bound to a live view

```csharp
var ordersView = from o in customer.Orders.AsLive()                 select new OrderInfo                 {
                     OrderID = o.OrderID,                     OrderDate = o.OrderDate,
                 };
```

```csharp
dataGrid1.ItemsSource = ordersView;
```

We can create a transaction and associate it with the view like this:

```csharp
var transaction = _scope.ClientCache.CreateTransaction();   ordersView.SetTransaction(transaction);
```

To create a child (nested) transaction, instead of calling the method **ClientCacheBase,CreateTransaction**, use the **ClientTransaction** constructor by passing it the parent transaction as a parameter:

```csharp
var transaction = new ClientTransaction(parentTransaction);
```

Once a transaction is associated with a view by calling **View.SetTransaction**; it tracks all changes made through that view, via data binding (for example, changes made by the end user in the grid bound to the view as in the example above) as well as programmatically in code. Rolling back the transaction (calling **ClientTransaction.Rollback**) cancels the changes tracked by that transaction.

It is often necessary to bind GUI controls to a single object \(as opposed to binding to a collection of objects\)\. A single object can’t be represented by a live view\, so we don’t have the convenience of View\.SetTransaction\|keyword=SetTransaction method\, but in this case we can use the **ClientTransaction.ScopeDataContext** method. In WPF and Silverlight, you can use this method to set the **DataContext** so it will be used for data bindings specified in XAML:

```csharp
DataContext = transaction.ScopeDataContext(order);
```

The resulting **DataContext** wraps the original one and performs the same data binding but with the additional benefit of all changes made through that data binding being tracked by the ‘transaction’, so they can be rolled back if necessary.

In WinForms, you can use the same **ScopeDataContext** and bind to the resulting object, for example, like this:

```csharp
var dataContext = transaction.ScopeDataContext(order);
```

```csharp
textBox.DataBindings.Add(new Binding("Text", dataContext, "OrderDate"));
```

Finally, sometimes you need to change (or add or delete) some entities in code, not through a live view or data binding, and want those changes to be tracked by a transaction. You can do it using the **ClientTransaction.Scope()** method. That method opens a *scope* for a transaction. When you modify entities while in the scope of a transaction, those changes are tracked by that transaction. That method is designed to be used with the 'using' construct that conveniently closes the scope on exit, like this:

```csharp
using (transaction.Scope()){    Customer.Orders.Add(order);}
```

All three methods of using transactions described above are demonstrated in the **Transactions** sample project that comes with [C1DataSource](/componentone/api/win/online-datasource/dotnet-framework-api/C1.Win.Data.Entity.4.8/C1.Win.Data.Entities.C1DataSource.html). It also demonstrates how a form with a **Cancel** button can be implemented inside another form that also has a **Cancel** button using child (nested) transactions.