我想做一些压力测试来模拟我的应用程序的多用户环境。我们使用实体框架 (EF) 作为我们的 ORM,使用 SQL Server 2008 R2 Enterprise 作为我们的后端。
这是模型的一部分 - 每个对象 ( NodeBase
) 都有Metadatum
对象 - 1:1 映射。似乎NodeBase
是首先写入,然后是Metadatum
第二个对象(或与Metadatum
对象的关联,不确定)。无论哪种方式,当我执行搜索时,我都会拉起 a NodeBase
,但它Metadatum
是空的。5 秒后,同样的搜索发现了该Metadatum
对象。:-/。令人沮丧。
在我的测试中,我有 2 个实例运行我们的应用程序(用于读取的 GUI,以及用于 R/W 的单元测试)。单元测试锤击数据库,创建对象的最坏情况读取和写入,GUI 正在读取数据库发生的所有更改(通过请求新数据锤击数据库)。
问题似乎是我的搜索引擎正在读取一个新写入的对象,并在对象的子对象和写入之前对其进行处理。当搜索去处理孩子时,有一个空异常。如果搜索等待几秒钟(没有比DateTime.Now.AddSeconds(-5)
看起来运行良好的更新),一切都会好起来的。虽然这适用于我当前的特定问题,但我怀疑它不会出现在应用程序的其他地方。
我试过的:
我编写代码中的事务(我可能没有所有选项都正确,或者可能做错了),但这似乎没有任何效果。每次写入都使用此事务:
using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions(){IsolationLevel = System.Transactions.IsolationLevel.Serializable})) { ContainerResult = OasisModelContainer.SaveChanges(false); OasisModelContainer.AcceptAllChanges(); transactionScope.Complete(); }
尝试先在单独的数据库上下文中将我的子对象抢先写入数据库,释放上下文,在当前上下文中重新读取子对象,附加到父对象(在事务中),但这不起作用.
其他只是闲逛的东西,关于 Stack Overflow 的提示等。
我尝试使用快照,但我不确定我是否正确使用它 - 我在我的数据库上设置了它:
ALTER DATABASE [ObjectModel] SET ALLOW_SNAPSHOT_ISOLATION ON ALTER DATABASE [ObjectModel] SET READ_COMMITTED_SNAPSHOT ON
我在想什么:
将 WriteLock 布尔值添加到在写入期间设置的每个对象,并且任何时候读取对象时,只有在清除 WriteLock 时才会继续。这具有巨大的影响(重构大量代码),并且不是可取的。
读取期间轮询 - 如果子对象为 Null,则延迟,再试一次。再次,潜在的巨大重构。
在写入期间向数据库添加表/数据库锁。我对 SQL Server 知之甚少,不知道这是聪明还是愚蠢。你能以不会导致死锁的方式锁定数据库或表吗?您可以设置 SQL Server 死锁超时,以便客户端应用程序不会超时吗?
任何帮助/指针/建议将不胜感激!