When to use the different update methods when working the LinqDataAdapter


I would like to get some clarity on when the different update methods should be used when working with the LinqDataAdapter. I’d been using the BeginUpdate/EndUpdate methods for everything, and then, accidentally, I found out that I didn’t need to, :slight_smile:. That’s why I’m asking.

Scenario 1: The Linq query directly returns the Table Definition objects.

	// Get data
	var orders = this._dataModule.DataAdapter.GetTable<Orders>();
	var order = orders.Where(o => o.Id == 1106).ToList().FirstOrDefault();

	// Update objects
	order.OrderStatus += 1;

	// Apply changes

In this case, since the object was returned from a direct Linq query, I don’t need to call DataAdapter.Update(order) or Order.BeginUpdate/Order.EndUpdate.

In this scenario, when using SendReducedDeltas, are only the deltas from fields changed sent or all the fields are considered as changed?

Scenario 2: The objects being changed are not returned directly by the Linq query

For example, in this query (taken from this question):

	// Aliases to make the query cleaned
	// These assignments do not cause any data request operations
	var orders = this._dataModule.DataAdapter.GetTable<Orders>();
	var orderDetails = this._dataModule.DataAdapter.GetTable<OrderDetails>();
	var products = this._dataModule.DataAdapter.GetTable<Products>();

	var query = orders
		.Where(o => o.OrderStatus != 128)
			o => o.Id,
			od => od.OrderId,
			(order, details) => new { Order = order, Details = details })
		.Select(g => g)
		.GroupBy(g => g.Order)
		.Select(g =>
			g.Key.Details = g.Select(r => r.Details).ToList();
			return g.Key;

In this case, the object was not directly returned by the Linq query, but instead, it was created by LinqToObject after retrieving the data, so I DO need to use the Update method:

	// Update objects
	order.OrderStatus += 1;

	// Apply changes

In this scenario, when using SendReducedDeltas, are only the deltas from fields changed sent or all the fields are considered as changed?

Is this correct?

And finally, under what circumstances do I need to use Order.BeginUpdate and Order.EndUpdate(DataAdapter) or Order.CancelChanges?



This is a rather complicated topic.

1. Changes tracking

There are 2 kinds of changes tracking - automatic and manual ones.

Automatic one is performed when 2 conditions are met:

  1. DataAdapter.UseBindableClass is set to true
  2. The result of the DA LINQ query is a value(s) of one the TableDefinition classes (ie when result type is not an anonymous class and the TableNameAttribute has been applied to it)

In this case the resulting data has tracking changes enabled.

Note: If the data requested won’t be changed (or these changes shouldn’t be persisted), consider setting DataAdapter.UseBindableClass to false to save CPU and memory

Manual changes tracking is performed via the NewRow / UpdateRow / DeleteRow methods

2. BeginUpdate / EndUpdate / CancelUpdate

These 3 methods are generated for each TableDefinition class.

You can easily take a look at these method’s code (they are literally 1-2 lines each):

  • BeginUpdate creates an internal clone of the current object
  • EndUpdate provides that internal clone to the Update method of the DataAdapter along with the current object values
  • CancelUpdate clears that internal cache object

It is not required to call these methods, but they provide a great benefit (see below)

3. Reduced Deltas

To successfully compose a delta for an object client code requires current values stored in the object fields. The downside of this approach is that the resulting delta will contain values for all object fields. Even more, it won’t be possible to reduce it to send only changed values to the server, because there is no information about old values.

Luckily the BeginUpdate / EndUpdate method pair does provide data required to compose a reduced delta (as it provides old object values)

So the general rule is

For reasonably-sized objects use non-reduced deltas and automatic change tracking until it becomes a bottleneck, then switch to explicit BeginUpdate / EndUpdate method calls.
For objects that contain significant amout of data (like binary blobs) consider to always use BeginUpdate / EndUpdate methods.


Ok, please let me know if what I understood is correct:

  1. If I use automatic change tracking, using ToList(), full non-reduced deltas will be sent to the server, but I don’t have to worry about keeping track of edits. Insert and Deletes, however, I have to perform explicitly using the adapter methods.

  2. If I use automatic change tracking, using ToDABindingList(), full non-reduced deltas will still be sent to the server, but I don’t have to worry about keeping track of edits, inserts or deletes, as long as I insert/delete objects through the list. Is this the case also when using ToList()?

  3. I can set DataAdapter.UseBindableClass to false, but I can still use manual change tracking via the NewRow / UpdateRow / DeleteRow methods. Or even with manual change tracking, I have to set DataAdapter.UseBindableClass to true?

  4. The only way to send ReducedDeltas is to manually use the BeginUpdate / EndUpdate / CancelUpdate methods.

  5. We should not worry about using ReducedDeltas unless we have blobs or very large objects, or it becomes a bottleneck.

Also, I noticed that in my NetStandard class library, the Table Definitions generated no longer include the BeginUpdate / EndUpdate / CancelUpdate methods. I’m guessing this is because ICloneable was not added until NetStandard 2.0. Is this going to be added anytime soon to the NetStandard table definitions?





No need to set it to true.

Correct. In the read world, thanks to data stream compression and database server optimizers there is no noticeable difference. Just remember about the network latency that will outmatch any reduced/non-reduced delta difference (unless rally slow network connection + blob data fields are present)

Regardinf .NET Standard / .NET Core - we’ll update the table definitions generator

Thanks, logged as bugs://82549

bugs://82549 got closed with status fixed.