【Dynamics CRM 2011】ワークフローやプラグインを動的に有効 / 無効化する
Dynamics CRMに登録されているワークフローやプラグインも、エンティティのレコードとして内部で保存されています。
どちらもStateCode / StatusCodeを所持しており、SDKのAPIで有効 / 無効を切り替えることも可能です。
ワークフローはともかく、何らかのバッチ処理で大量のデータを処理したい場合はプラグインが有効になっているとどうしてもその分処理時間が長くなってしまうので、事前にどうでもいいプラグインを無効化するところまでバッチ化してしまうのも一つの手です。
対象のレコードを抽出する(SQL)
エンティティなので普通にSQLでもとってこれます。まずはワークフロー。
SELECT * FROM Workflow WHERE [type] = 1
Workflow.type = 1で抽出することで、定義済みのワークフローのレコードを取得することが出来ます。
他のエンティティの例に漏れず、[Workflowid]と言うカラムにそのレコードのGUIDがあります。
流石に*で検索するとよくわからん、って場合はこの辺を見ておけばいいと思います。
SELECT name ,statecode ,statuscode ,workflowid FROM Workflow WHERE [type] = 1
ワークフローは「Statecode = 1 かつ Statuscode = 2」だとアクティブ、「Statecode = 0 かつ Statuscode = 1」だと非アクティブです。
どっちか片方取ってきたい場合は適当にWHEREに入れちゃいましょう。
次はプラグインです。「Sdkmessageprocessingstep」と言うやたら長い名前のエンティティに入っています。
SELECT * FROM Sdkmessageprocessingstep WHERE IsCustomizable = 1 AND IsHidden = 0
WHEREなしで調べようとすると結構だるいです。(内部でのみ使われている何かが大量にヒットする)
もちろんこれも[Sdkmessageprocessingstepid]と言うカラムを持っています。
SELECT name ,eventhandlername ,sdkmessageidname ,statecode ,statuscode ,Sdkmessageprocessingstepid FROM Sdkmessageprocessingstep WHERE IsCustomizable = 1 AND IsHidden = 0
こんな感じのクエリを投げればどれがどれだかなんとなーくつかめると思います。
プラグインのほうは「Statecode = 0 かつ Statuscode = 1」だとアクティブ、「Statecode = 1 かつ Statuscode = 2」だと非アクティブです。ワークフローとは逆ってことですね。
対象のレコードを抽出する(SDK)
当たり前ですがSDKのAPIで取得することも出来ます。改めて書く必要があるのか、って感じですが。
// Get Workflow var w = new QueryExpression("workflow") { ColumnSet = new ColumnSet("name", "statecode", "statuscode"), }; w.Criteria.AddCondition("type", ConditionOperator.Equal, 1); var workFlows = service.RetrieveMultiple(w).Entities .Select(x => new { Id = x.Id, Name = x.Attributes["name"] as string, IsDisabled = ((int) x.Attributes["statecode"]) == 0 && ((int) x.Attributes["statuscode"]) == 1, } ); // Get Plugin var p = new QueryExpression("sdkmessageprocessingstep") { ColumnSet = new ColumnSet("name", "eventhandlername", "sdkmessageidname", "statecode", "statuscode"), }; p.Criteria.AddCondition("iscustomizable", ConditionOperator.Equal, 1); p.Criteria.AddCondition("ishidden", ConditionOperator.Equal, 0); var plugins = service.RetrieveMultiple(p).Entities .Select(x => new { Id = x.Id, Name = x.Attributes["name"] as string, EventHandlerName = x.Attributes["eventhandlername"] as string, SdkMessageIdName = x.Attributes["sdkmessageidname"] as string, IsDisabled = ((int) x.Attributes["statecode"]) == 1 && ((int) x.Attributes["statuscode"]) == 2, } );
有効 / 無効の切り替えを行う
SQLを直に投げるのはやんわりと禁止されてるので、SDKのやり方だけ。
普通にSetStateRequestをExecuteから投げてあげれば大丈夫です。
// Workflow foreach (var workFlow in workFlows) { // 無効なら有効に、有効なら無効に切り替える var statecode = workFlow.IsDisabled ? 1 : 0; var statuscode = workFlow.IsDisabled ? 2 : 1; service.Execute(new SetStateRequest { EntityMoniker = new EntityReference("workflow", workFlow.Id), State = new OptionSetValue(statecode), Status = new OptionSetValue(statuscode), }); } // Plugin foreach (var plugin in plugins) { // 無効なら有効に、有効なら無効に切り替える var statecode = plugin.IsDisabled ? 0 : 1; var statuscode = workFlow.IsDisabled ? 1 : 2; service.Execute(new SetStateRequest { EntityMoniker = new EntityReference("sdkmessageprocessingstep", plugin.Id), State = new OptionSetValue(statecode), Status = new OptionSetValue(statuscode), }); }
まとめ
RESTを使っても出来るんじゃないかなぁ、と思います。試してないですが。
なんにしろ、この辺の操作も自動化できるってことはtipsとして知っておいて損はないです。