どうも、前回自己紹介エントリを書いた佐野です。皆さんいかがお過ごしでしょうか?
今回はPower Platformリレーということで、Power Platformについて書いていくのですが、やはりPower Platformでシステムを作り込むのは難しいですね。社内でちょっとDXする程度のものならいいですが、ちゃんとしたDB設計や複雑なロジックを組もうとするとすぐに行き詰ります。
この記事では、そんな「ちゃんとしたDB設計」をして行き詰った事例を、同じように行き詰る人が出る前に共有しておこうと思います。
(結論だけ見たい方は最後の「まとめ」を参照)
Dataverseで参照型を使う
ことの発端はOJT最初期の頃、研修でPower Platformの素晴らしさを聞いた直後で、Power Platformなら何でもできると幻想していた頃のことです。
Power Appsでとあるシステムを作ることになって、自分は高専生の頃DBを触っていた経験があったので、DBに近いものを作ろうと思ってDataverseに手を出しました。
簡単にですが、下のスクショのような設計にしました。学校から保護者に対し連絡できるようなシステムを考えていたので、学校・生徒・保護者のテーブルがあり、生徒は学校と保護者に対して参照を持っています。
例え2つの参照を持っていても、フォームを使って生徒登録画面を作る程度であれば簡単にできます。下のように、フォームのデータソースを設定すれば自動でいい感じにしてくれるので気にする必要はありません。
Dataverseのテーブルにフォームを使わずデータを入れる
しかし、ここからUXを考えて一工夫入れるとなると、話は違ってきます。
今回は学校から保護者に連絡するシステムなので、生徒を登録するときに保護者も一緒に登録したくなることもあると思います。そういった場合、2つのテーブルを一度に操作するため、フォームを使うことはできません。
「生徒と保護者を一つのテーブルにまとめればいいのでは?」と思う人もいるかもしれませんが、兄弟の場合など、複数の生徒に対し1人の保護者が紐づくこともあり得るので、今回は一つのテーブルにまとめる選択肢はないものとします。
フォームを使わない場合は下のスクショのように入力を並べ、登録ボタンを押したときにCollect関数を使用してデータ追加を行います。
実際の登録ボタンのOnSelect関数は以下のようにしました。
Collect(test_保護者, {メールアドレス: parent_mail.Text, 名字: parent_lastname.Text, 名前: parent_firstname.Text});
Collect(test_生徒, {名字: lastname.Text, 名前: firstname.Text, 学校: school.SelectedText.Value, 保護者: parent_mail.Text});
Navigate(main);
普通のDBでは、リレーションはprimary keyを持つことで実現されているので、生徒テーブルの学校列と保護者列にも「プライマリ名の列」の値を設定してみました。しかし、下の様なエラーが発生します。
どうやらprimary keyではなく「DataEntity」型の何かが必要なようです。
調べてみると…Power Apps Communityのフォーラムで衝撃的な事実が発覚しました。
I have made a test, and the issue is confirmed on my side. There is no way to provided a DataEntity type value for a Lookup type column of CDS entity within PowerApps currently, I afraid that there is no way to add new record into a CDS Entity which contains a Lookup column using Collect function.
「no way」つまり「DataEntity」型の何かを取得する方法はない、ということです。
一応この回答が投稿されたのは2018年なので、実は何かしら方法があるのかもしれませんが、少なくとも自分が調べた限りではそもそも「DataEntity」に引っかかる記事は殆ど無く、LookUp関数の結果を放り込んでみたりもしましたが、エラーは消えるもののレコードが追加されている様子はありませんでした。
まとめ
要約すると、Dataverseの参照列を持つテーブルにCollect関数でデータ挿入するには参照先の「DataEntity」が必要だが、現在「DataEntity」型の値を取得する方法は存在しない、ということです。
現状のPower Apps+Dataverseの環境で参照を使うのはおすすめしません。
もしリレーションを使うのであれば、参照ではなくprimary keyをテキストで持たせるか、画面と1対1になるようなテーブルにしたほうがいいのではないか思います。
2021/6/10追記:
LookUp関数でできるよ、という指摘記事がありました。
LookUp関数では一度試してできなかったため、できないのだと思っていましたが、こちらでも再検証してみたところ、できました。
Set(parent, Collect(test_保護者, {メールアドレス: parent_mail.Text, 名字: parent_lastname.Text, 名前: parent_firstname.Text}));
Collect(test_生徒, {名字: lastname.Text, 名前: firstname.Text, クラス: class.Text, 学校: LookUp(test_学校, 学校名 = school.SelectedText.Value), 学年: Value(grade.Text), 保護者: Last(parent)});
以前できなかったのはパラメータに抜けがあったのが原因で、エラーが出なかったため気付けなかったようです。Power Appsはなぜかそういうところを一切指摘してくれないようなので、皆さんもお気を付けください。
ご指摘ありがとうございました!