4D v17 が紹介されています。 ORDAORDAは、4D開発者に新しい可能性の世界を開く、4Dの大きな進化です。ORDAを使用する利点の1つは、レコードの ロックに関連しています。ORDAのロック機構を紹介した後、ORDAシリーズを続けることで、ORDAで楽観的ロックで効率的に作業する方法を発見することができます。
楽観的ロックの概要
楽観的ロックモードでは、レコードは 更新される前に明示的にロック されることはない。
楽観的ロックは、レコードのスタンプに 依存します。各レコードには内部スタンプがあり、レコードが データベースに 保存されるたびに自動的にインクリメントされます。エンティティをロードしてからレコードが更新された場合、save(),drop(),lock()メソッドは、スタンプが変更されたことを示す特定のステータス・コードを返します。
レコードとエンティティー
レコードとは、データベース内の物理的なレコードで、エンティティを通じてアクセスされます。エンティティは レコードの参照先です(用語集のエンティティの項を参照)。レコードはエンティティを通してロックされ、ロックが解除されます。
コード例
以下の例では、メソッドが失敗する2つのシナリオを扱います。 save()メソッドが失敗する2つのシナリオを扱います。
C_OBJECT($status;$employee)
// Get the first employee whose last name is "Smith"
$employee :=ds.Employee.query("lastName=:1"; "Smith").first()
If ($employee#Null)
$employee .lastName:="Wates" // Update employee's last name
$status :=$employee.save()// Save employee
if (Not($status.success))// The save action fails
Case of
// The record has been updated in database since the entity was loaded
: ($status.status=dk status stamp has changed)
alert ("ロードしてから誰かがレコードを更新しました")
//The record is locked by another process
: ($status.status=dk status locked)
alert ("誰かがレコードをロックしました")
End case
end if
end if
ケース 1: エンティティが変更された場合
エンティティをロードした後にデータベースでレコードが更新された場合、返される$status オブジェクトは以下のようになります。
{ "status": 2, "statusText": "Stamp has changed", "success": false }
CASE 2: ENTITY は既にロックされている
データベース内のレコードが他のプロセスによって既にロックされている場合、返される$status オブジェクトは以下のようになります。
{ "status": 3, "statusText": "Already Locked", "lockKind": 1, "lockKindText": "Locked By Record", "lockInfo": { "task_id": 5, "user_name": "Mary Smith", "user4d_id": 1, "host_name": "iMac27-Program6", "task_name": "P_10", "client_version": -1610541312 }, "success": false }
一般的なシナリオ
メソッドに付随する save()メソッドを使用します。 ORDAは非常に便利なオプションを提供します。 dk auto merge.
dk auto mergeは、メモリにロードされたエンティティで行われた更新を、データベースのレコードで行われた更新と自動的にマージ することを試みます。しかし、他のユーザーがデータベースのレコードで更新したのと同じプロパティをロードしたエンティティで更新した場合、失敗することがあります。
したがって、 これを管理するために、2つのオプションを提供します。
1- データベースで行われたアップデートを上書きする
以下の例では save()メソッドに dk auto mergeは失敗します。
他のプロセスによってデータベースで行われた更新を上書きしたいことは確かです。
この場合、次のように管理します。
1- 保存する前に clone() メソッドを使用しています。これは、更新されたエンティティに新しい参照を作成します。後で再利用するために、エンティティのコピーを作成するのは便利です。
このとき save()メソッドが失敗した場合。
2- reload() メソッドを使用して、データベースの レコードから エンティティを再読み込みし、最新のスタンプを取得できるようにします。
3- 複製されたエンティティを使用して、更新を再適用する。
4- エンティティを再度保存し、返されたステータスをテストする。
C_OBJECT($status;$employee;$clonedEmployee)
// Get the first employee whose last name is "Smith"
$employee :=ds.Employee.query("lastName=:1"; "Smith@").first
()
If ($employee#Null)
// Update the last name
$employee .lastName:="Dunaway"
// Clone the loaded entity
$clonedEmployee :=$employee.clone()
// Save the entity with auto merge option $status :=$employee.save(dk auto merge)
// The save action fails
While (Not($status.success) ))
// The auto merge failed
If
($status.status=dk status automerge failed)
// Reload the entity. The stamp will be updated
$employee .reload()
// Reapply the update on last name $employee lastName :=$clonedEmployeelastName // Save the entity $status :=$employee.save(dk auto merge)
End if
End while
End if
2- エンティティとレコードの間の競合を手動で管理するためのユーザーインターフェイスを構築する。
ORDAは、ユーザーが自分の更新と同時に行われる他のことを選択できるようなインターフェイスを構築するのに役立つメソッドを提供しています。
これらのメソッドの概要を簡単に説明します。詳細については、ドキュメントをご覧ください。
- touchedAttributes()メソッド: エンティティをロードまたは保存した後にアクセスされた属性を返します。
- diff()メソッド: 2つのエンティティを比較します。
提供されたHDIでは、このようなインターフェイスを構築する方法を見ることができます。