この記事のゴール
運用中のシステムのEntityにUnique制約を付けたAttributeを追加する。
発生した現象
運用中のEntityに新しくUnique制約が付いたAttributeを追加する必要が生じた。
ここではCompanyに新しくUnique制約を付けたCodeを追加する。
すでにレコードが存在しているので、デフォルト値「空値」を複数のレコードに設定しようとして一意制約違反が発生している。
試したこと
- デフォルト値が一意になるように設定する
- Unique制約を後から設定する
デフォルト値が一意になるように設定する
ぱっと思いつく方法は
-
GUIDを生成して格納する
残念ながら安直にサーバアクションを設定することができない模様。裏でSQLに変換されるのだろうし、デフォルト値に何が設定できるのか少し調べただけではわからなかった。
-
該当レコードのIDを文字列に変換して格納する
Guidと同じ理由で断念。
すぐには解決できそうにないので2つ目の施策を考える。
Unique制約を後から設定する
既視感、よく考えたらPythonのDjangoでよくやっていた方法。
-
既存Entityに新しいAttributeをUnique制約なしに追加する
まずはDataTypeとLength、IsMandatoryを設定しUnique制約を付けずにPublishする。 -
新しいAttributeに一意な値を設定する
既存のレコードに対して新しく追加されたAttributeに一意な値を設定するタイマーを作成する。
ここではCodeというAttributeに同レコードのIDを設定することで一意性を担保している。
タイマーを実行し、一意の値を設定する。
-
新しく追加したAttributeにUnique制約を付加し、Publishする
まとめ
運用中のシステムのすでにレコードが存在するEntityにUnique制約を付けたAttributeを追加必要が出た場合には、以下の手順を実施することで実現できる。
- 既存Entityに新しいAttributeをUnique制約なしに追加する
- 新しいAttributeに一意な値を設定する
- 新しく追加したAttributeにUnique制約を付加する
本番環境にLifeTimeで配置して終了とはいかず、タイマーを動かしてから再度本番への変更が必要となる。本番適用のためには、事前の十分な計画とテストが必要。