在進行交易的過程中,主要有三個 Timeout 時間。而真正的可交易時間,是取下面三者的最小值。
Command.CommandTimeout
這個 timeout 是最基本的 Timeout 時間,預設為 30 秒。這個設定是執行sql指令的可執行時間。
TransactionScope 的Timeout
在執行交易時,TransactionScope 也有一個 Timeout 時間。這個時間是由 TransactionScope 的建構子中的參數來指定的。預設值是60秒,可由 TransactionManager.DefaultTimeout 取得設定值。
TransactionManager 的 MaximumTimeout
TransactionManager 裡頭也有一個 timeout。這個 timeout 時間是是全機的交易管理員的最大可交易的時間。在 .NET 2.0 預設可由子層的 config 或程式來覆寫。但在 .NET 4.0,就不能被子層來覆寫了,如果需要修改,則必須到 %windir%\Microsoft.NET\Framework\v4.0.30319\Config\machine.config (32 位元),或 %windir%\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config 中以管理員的權限進行修改。
<system.transactions>
<machineSettings maxTimeout="02:00:00" />
</system.transactions>
Azure 中設定
微軟的 Windows Azure Cloud Service 環境中,當然我們可以使用遠端桌面的方式,連線到每個伺服器進行上述的修改。但是一旦重新掛載作業系統後,這些人工設定又全部跑掉必須重設,非常不人道。幸好部署時有 Start Task 的機制, 可以執行 cmd 的指令。cmd 指令如下
windir%\system32\inetsrv\appcmd set config /commit:MACHINE /clr:4 -section:machineSettings -maxTimeout:02:00:00
此指令必須寫成 .cmd 檔,放在 WebRole 或 WorkerRole 的 project 內,以 content/Always copy to Output Directory 的型式加入專案
接著,在Azure 專案的 ServiceDefinition.csdef 中加上 Startup Task 的指令
<Startup> <Task commandLine="timeout.cmd" executionContext="elevated" taskType="simple" /> </Startup>
如下圖
其中 executeContext=”elevated” 指的是必須以管理員的權限進行修改
結論
TransactionScope 的 Timeout 設定有點複雜,除了.NET 版本,32/64 版本,%windir%\system32\ 與 %windir%\SysWOW64\ 的不同外,現在又增加了雲端的設定。真是不太容易。