一个 AttributeExternalKey
类型的属性,on_target_delete
设置为 DEL_MANUAL
,但是当删除对应的对象时,没有被阻止,只是提示此属性将被重置为空。
一开始以位遇到新版本的 BUG 了,本意是打算通过 DEL_MANUAL
避免意外删除的,比如 品牌 被 物理设备使用,要删除一个品牌,当这个品牌还在被某些设备使用时,不应该被删除。印象中 2.5 是可以做到的。
于是搭了个 2.5 版本做实验,却发现结果和新版的一样。
经过反复测试,发现是自己记错了,on_target_delete
的作用是:当删除一个对象时,如果这个对象会破会其他对象的数据完整性,此时该如何处理,DEL_MANUAL
是需要手工先删除完整性被破坏的对象,DEL_AUTO
会自动删除。还拿品牌举例,如果物理设备的品牌属性被设置为必填项,那么当删除一个仍然被引用的品牌时,会导致对应的设备数据完整性破坏,为了数据一致性,这些设备也不应该存在,所以也要删除,如果是 DEL_MANUAL
就要求人工删除,DEL_AUTO
则会要求自动删除。显然,这里应该用 DEL_MANUAL
。
我之所以会遇到这个疑问,是因为我这次定义的 AttributeExternalKey
类型的属性是非必填项,删除对应的对象,不会导致数据不一致问题,因此简单的将该属性重置为空即可。此时 DEL_MANUAL
没有用。
那么,如果我即想要允许设备的品牌留空,又想实现被引用的品牌对象不允许删除的效果,该怎么做呢?答案是通过 CheckToDelete
自定义删除规则。考古 19 年的代码,示例如下:
<method id="CheckToDelete" _delta="define">
<static>false</static>
<access>protected</access>
<type>Overload-DBObject</type>
<code><![CDATA[
public function CheckToDelete(&$oDeletionPlan)
{
$oSearch = DBObjectSearch::FromOQL_AllData("SELECT Controller WHERE status='production' AND secret_id=:secret_id");
$oSet = new DBObjectSet($oSearch, array(), array("secret_id" => $this->GetKey()));
if ($oSet->Count() > 0)
{
// 被在线状态Controller使用的Seret不允许直接删除
$oDeletionPlan->AddToDelete($this, null);
$oDeletionPlan->SetDeletionIssues($this, array('有在线状态K8S控制器使用此Secret对象,不允许直接删除'), true);
$oDeletionPlan->ComputeResults();
return false;
}
return parent::CheckToDelete($oDeletionPlan);
}
]]></code>
</method>
可以通过 iApplicationObjectExtension 接口统一实现删除前检查。检查所有 _list,如果不为空,则拒绝删除