Using UpdatePanels inside a Repeater

Sometimes you might find it necessary to place an UpdatePanel control inside the ItemTemplate of a Repeater or other databound control. Normally you would probably just put the UpdatePanel outside of the repeater, but this can cause other problems. First of all, it makes the size of the update much larger. Secondly, I ran into a situation where I was using the curvyCorners system for rounding the corners of DIVs that were inside my ItemTemplate.

First of all, it was problematic to run the javascript to round the corners again after the AJAX was done. You can do it using the ScriptManager.RegisterStartupScript method, so long as you place the recommended script code directly in the script block, and don’t use the window.onload event. However, I found that it is VERY slow since it is running on several DIVs.

Therefore, I decided to use individual UpdatePanel controls inside each DIV that update just the data that needs updating. The problem I encountered is that I couldn’t reference Container.DataItem for my data-binding inside the UpdatePanel like I could when it wasn’t there.

The workaround I found was to use type-casting, and instead reference CType(Container, IDataItemContainer).DataItem. This fixed the problem without any side effects, at least so far. Each update panel is independently updated, and the rounded corners stay intact on my DIVs.

Note that I didn’t have any problems using the Eval method, just DataBinder.GetPropertyValue and other DataBinder methods that require that you pass the DataItem as a parameter.

Using Transactions With DataSets

One of the major shortcomings of the ADO.NET dataset system, in my opinion, is the lack of support for transactions. In .NET 2.0 this situation was somewhat addressed by the addition of the System.Transactions namespace. However, this namespace has two flaws when it comes to using it with a DataSet. First, if you open more than one database connection within the same TransactionScope, it will use the Distributed Transaction Coordinator (MSDTC) instead of more efficient and configuration free database transactions. Second, if you require backwards compatibility with SQL 2000, it will ALWAYS use the MSDTC even if you open just a single database connection. The first issue can be addressed by opening the connection in advance and passing it to each TableAdapter that you use. Note that you’ll need to change the Connection property on the TableAdapter from Friend (internal) to Public in the DataSet designer if the DataSet is in a DLL.

The second issue is a bit trickier to solve. In this case, you also need to open a single database connection as before, but then use an old fashioned SqlTransaction instead of the System.Transactions namespace. Then both the SqlConnection and SqlTransaction need to be set on each TableAdapter. This can be done by adding a special helper function to the partial class for the TableAdapter, as shown below.

Namespace DataSetTableAdapters

Partial Class TableAdapter

Public Sub SetConnection(ByVal cn As SqlConnection, trans As SqlTransaction)
Connection = cn
For Each cmd As SqlCommand In Me.CommandCollection
cmd.Transaction = trans
Next
Adapter.UpdateCommand.Transaction = trans
Adapter.InsertCommand.Transaction = trans
Adapter.DeleteCommand.Transaction = trans
End Sub

End Class

End Namespace