I’m storing a dataset in an ASP.Net WebApplication-Cache. Every user in this intranet-app uses the same instance. On insert/update/delete-actions the database will be updated and the dataset is modified accordingly.
But rarely I get an exception that indicates that I’ve missed something. I assume that it must have something to do with thread safety.
Collection was modified; enumeration operation might not execute
In lines where i access a DataTable in the Dataset, for example:
Dim view As New DataView(dsERP.ERP_Charge, filter, sort, _ Data.DataViewRowState.CurrentRows)
It was apparently changed by another thread while the view enumerates the datatable.
What is the best way to make this thread safe?
Edit: as you’ve mentioned i need to lock the objects on add/edit/delete operations.
MSDN* says that a DataSet is thread-safe for multiple users. What does this mean, are the DataTables in the Dataset also thread-safe? And how to lock a single datatable on write-operations and not the whole dataset?
*ADO.NET – Multithreaded Programming
ADO.NET is optimized for performance, throughput, and scalability. As a result, the
ADO.NET objects do not lock resources and must only be used on a single thread. The one
exception is the DataSet, which is thread-safe for multiple readers. However, you need
lock the DataSet during writes.
This is the property that returns the dataset:
Public ReadOnly Property dsERP() As ERPModel.dsERP Get If Cache("DS_ERP") Is Nothing Then Cache("DS_ERP") = New ERPModel.dsERP FillDataSet() End If Return DirectCast(Cache("DS_ERP"), ERPModel.dsERP) End Get End Property
Thanks to casperOne i’ve modified the insert/update and delete operations in the following way(dsRma is a dataset):
Dim success As Boolean SyncLock dsRMA.RMA success = insert() End SyncLock
First, does it work now if another thread tries to enumerate the RMA-Table? Second, is it sufficient to lock the datarow that gets updated instead of locking the whole datatable(see below)?
Dim thisRMA As ERPModel.dsRMA.RMARow = dsRMA.RMA.FindByIdRMA(Me.IdRma) Dim success As Boolean SyncLock thisRMA success = update(thisRMA) End SyncLock