XE7以前でFireDACのMS SQL Serverから返されるデッドロックエラー(1205)の判定
問題
MS SQL Serverのロックマネージャは、デッドロックを検出すると、クライアントにエラーコード「1205」を返します。MS SQL Serverのデッドロックの検出方法とエラーコードについては、以下の情報を参考ください。
FireDACでは、データ更新時にエラーが発生した場合の処理をTFDConnection.OnErrorイベントなどへ記述し、デッドロックが発生した場合は、EFDDBEngineException.kind=ekRecordLockedで判定できます。EFDDBEngineExceptionの使用例は、以下の通りです。
Delphiの場合
if E is EFDDBEngineException then
begin
case EFDDBEngineException(E).Kind of
ekRecordLocked:
//デッドロック時の処理を記述
end;
なお、EFDDBEngineExceptionのKindプロパティで取得できる種類については、以下の情報を参考ください。
本来であれば、デッドロックの判定は上記の方法で行えるのですが、MSSQLServerから返されるエラーコードが「1205」の場合、EFDDBEngineException.kindの値は、「ekRecordLocked」ではなく、「ekOther」になります。これは、FireDACではデータベースから返されるネイテイブのエラーコードによって、エラー種類の判別を行っていますが、エラーコード「1205」に関する判定処理が抜けており、結果としてどのエラーにも属さない「ekOther」になるFireDACの不具合です。
解決
こちらの症状は、XE7で修正されています。
XE7以前のバージョンで改善するには、以下の該当するユニットファイルをご自身のプロジェクトへコピーし、修正してください。修正するソースコード行は、FireDACのバージョンやアップデートによって若干異なりますので、その場合は“ekRecordLocked”のキーワードで該当するファイル内を検索してください。
修正するファイル名(FireDAC.Phys.MSSQL.pas)
case ANativeError of
1204,
1205, // 追加
1222:
AKind := ekRecordLocked;