【发布时间】:2011-07-22 21:20:12
【问题描述】:
我将数据集存储在 ASP.Net WebApplication-Cache 中。此 Intranet-app 中的每个用户都使用相同的实例。在插入/更新/删除操作时,数据库将被更新并相应地修改数据集。
但我很少遇到表明我遗漏了什么的异常。我认为它必须与线程安全有关。
Collection was modified; enumeration operation might not execute
在我访问数据集中的数据表的行中,例如:
Dim view As New DataView(dsERP.ERP_Charge, filter, sort, _
Data.DataViewRowState.CurrentRows)
当视图枚举数据表时,它显然被另一个线程更改了。
使这个线程安全的最好方法是什么?
编辑:正如您所提到的,我需要在添加/编辑/删除操作时锁定对象。 MSDN* 表示 DataSet 对多个用户来说是线程安全的。这是什么意思,Dataset 中的 DataTables 也是线程安全的吗?以及如何在写操作上锁定单个数据表而不是整个数据集?
*ADO.NET - 多线程编程
ADO.NET 针对性能、吞吐量和可扩展性进行了优化。结果, ADO.NET 对象不锁定资源,只能在单个线程上使用。唯一的那个 例外是 DataSet,它对多个读取器是线程安全的。但是,您需要 在写入期间锁定 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
感谢 casperOne,我通过以下方式修改了插入/更新和删除操作(dsRma 是一个数据集):
Dim success As Boolean
SyncLock dsRMA.RMA
success = insert()
End SyncLock
首先,如果另一个线程尝试枚举 RMA-Table,它现在可以工作吗?其次,锁定更新的数据行而不是锁定整个数据表是否足够(见下文)?
Dim thisRMA As ERPModel.dsRMA.RMARow = dsRMA.RMA.FindByIdRMA(Me.IdRma)
Dim success As Boolean
SyncLock thisRMA
success = update(thisRMA)
End SyncLock
【问题讨论】:
-
为什么要缓存数据集?
-
@Lasse:主要是为了避免在任何用户的每次回发时永久访问数据库。但是由于这样的问题,我不再对这个决定很满意。此外,大多数操作是插入和更新,因此无论如何我也必须更新数据库。
-
通过添加锁,您有效地序列化了对数据集的所有访问,您基本上将您的多用户 Web 应用程序变成了一次一个用户类型的应用程序.这真的是你想要的吗?如果没有,放弃缓存的数据集,与数据库对话。缓存那些不会改变的东西,并为那些改变的东西访问数据库,让它担心锁定什么以及何时锁定。毕竟,这是数据库最擅长的。
标签: .net asp.net multithreading caching ado.net