【ITニュース解説】Dataverse internals: how to get the Sitemap of a given Model Driven App 🤔
2025年09月07日に「Dev.to」が公開したITニュース「Dataverse internals: how to get the Sitemap of a given Model Driven App 🤔」について初心者にもわかりやすいように丁寧に解説しています。
ITニュース概要
DataverseのModel Driven Appのサイトマップは、アプリと直接紐付かず、appmodulecomponentテーブルを介して関連する。アプリのサイトマップ情報を取得するには、この中間テーブルを使ったSQLクエリやFetchXMLで抽出できる。
ITニュース解説
Dataverseは、Microsoftが提供する強力なデータプラットフォームで、Power AppsやDynamics 365といったビジネスアプリケーションの基盤となっている。システムエンジニアを目指す上では、このDataverseがどのようにデータを管理し、アプリケーションを構築しているかを理解することが重要だ。今回は、Dataverseで作成される「モデル駆動型アプリ(Model Driven App)」とそのアプリのナビゲーションを定義する「サイトマップ(Sitemap)」の関係、そしてそのサイトマップの情報をプログラムから効率的に取得する方法について解説する。
モデル駆動型アプリは、Dataverseに格納されたデータに基づいて自動的にユーザーインターフェースが生成されるビジネスアプリケーションだ。このアプリには、ユーザーがシステム内をスムーズに移動できるように、メニューやリンクが構成されたサイトマップが必ず一つ関連付けられている。通常、一つのアプリには一つのサイトマップが直接紐づいている(1対1の関係)と直感的に考えるかもしれない。しかし、Dataverseの内部構造では、この関係は少し複雑になっている。
実際には、モデル駆動型アプリの情報が格納されているappmoduleテーブルと、サイトマップの情報が格納されているsitemapテーブルは、直接関連付いていない。その間に「appmodulecomponent」という中間テーブルが介在しているのだ。このappmodulecomponentテーブルは、モデル駆動型アプリがどのような構成要素(コンポーネント)で成り立っているかを管理する役割を担っている。サイトマップもアプリの重要な構成要素の一つとして、このappmodulecomponentテーブルを介してアプリと結びつけられている。
appmodulecomponentテーブルには「componenttype」という属性があり、これが構成要素の種類を示している。サイトマップの場合、このcomponenttypeの値は「62」と定義されている。したがって、特定のモデル駆動型アプリのサイトマップ情報を取得するには、アプリの情報、中間テーブルであるappmodulecomponentの情報、そしてサイトマップ自体の情報を、それぞれの関連性を辿りながら検索する必要がある。
この関係性を理解することで、私たちはSQLクエリ、またはDataverseに特化したクエリ言語であるFetchXMLを使って、目的のサイトマップ情報を正確に取得できる。
まず、SQLクエリでの取得方法を見てみよう。
1SELECT TOP 1 2 am.appmoduleid, 3 am.name, 4 am.uniquename, 5 sm.sitemapid, 6 sm.sitemapname, 7 sm.sitemapxml 8FROM 9 appmodule am 10 INNER JOIN appmodulecomponent amc ON am.appmoduleidunique = amc.appmoduleidunique 11 INNER JOIN sitemap sm ON amc.objectid = sm.sitemapid 12WHERE 13 amc.componenttype = 62 -- 62: sitemap 14 and am.uniquename = 'YOUR APP UNIQUE NAME'
このSQLクエリは、指定したモデル駆動型アプリに紐づくサイトマップの情報を取得する。
SELECT句では、アプリの識別子(appmoduleid)、アプリ名(name)、ユニーク名(uniquename)と、サイトマップの識別子(sitemapid)、サイトマップ名(sitemapname)、そしてサイトマップの構造を定義するXMLデータ(sitemapxml)を取得するよう指定している。TOP 1は、複数のサイトマップが見つかった場合に最初の1件のみを取得するという指示であり、一つのアプリには一つのサイトマップが紐づくという原則に基づいている。
FROM appmodule amは、appmoduleテーブルから検索を開始し、このテーブルに「am」という別名を付けている。
次にINNER JOINを使って他のテーブルを結合している。
INNER JOIN appmodulecomponent amc ON am.appmoduleidunique = amc.appmoduleiduniqueは、appmoduleテーブルとappmodulecomponentテーブルを、それぞれのユニークなアプリID(appmoduleidunique)をキーとして結合している。これにより、アプリと、そのアプリが持つ構成要素を結びつける。
さらに、INNER JOIN sitemap sm ON amc.objectid = sm.sitemapidで、appmodulecomponentテーブルとsitemapテーブルを結合している。ここでappmodulecomponentテーブルのobjectidが、サイトマップの識別子(sitemapid)と一致することで、特定の構成要素がどのサイトマップであるかを特定している。
WHERE句では、取得するデータを絞り込むための条件を指定している。
amc.componenttype = 62は、appmodulecomponentテーブルの中で、構成要素の種類がサイトマップ(componenttypeが62)であるレコードのみを対象とする。
and am.uniquename = 'YOUR APP UNIQUE NAME'は、検索対象とするモデル駆動型アプリを、そのユニーク名で指定する。この'YOUR APP UNIQUE NAME'の部分を、実際に調べたいアプリのユニーク名に置き換えて使用する。
次に、FetchXMLを使った取得方法を見てみよう。FetchXMLは、DataverseやDynamics 365のデータに対してクエリを実行するために設計されたXMLベースの言語である。
1<fetch top="1"> 2 <entity name="appmodule"> 3 <attribute name="appmoduleid" /> 4 <attribute name="name" /> 5 <attribute name="uniquename" /> 6 <link-entity name="appmodulecomponent" to="appmoduleidunique" from="appmoduleidunique" alias="amc" link-type="inner"> 7 <link-entity name="sitemap" to="objectid" from="sitemapid" alias="sm" link-type="inner"> 8 <attribute name="sitemapid" /> 9 <attribute name="sitemapname" /> 10 <attribute name="sitemapxml" /> 11 </link-entity> 12 <filter> 13 <condition attribute="componenttype" operator="eq" value="62" /> 14 </filter> 15 </link-entity> 16 <filter> 17 <condition attribute="uniquename" operator="eq" value="YOUR APP UNIQUE NAME" /> 18 </filter> 19 </entity> 20</fetch>
FetchXMLの構造も、SQLクエリと基本的には同じロジックで構成されている。
<fetch top="1">は、SQLのSELECT TOP 1に相当し、取得するレコード数を制限する。
<entity name="appmodule">は、SQLのFROM appmoduleに相当し、appmoduleテーブルを主エンティティとして指定する。
<attribute name="..." />は、SQLのSELECT句で指定する列(属性)と同じだ。
<link-entity name="..." ...>は、SQLのINNER JOINに相当する。toとfrom属性で結合条件を指定し、aliasで別名を付ける点もSQLと同様だ。ここではappmoduleからappmodulecomponentへ、そしてappmodulecomponentからsitemapへと、二段階でテーブルを結合していることがわかる。
<filter>と<condition>タグを使って、SQLのWHERE句と同じように検索条件を指定する。componenttypeが62であること、そしてアプリのuniquenameが指定した値であること、という二つの条件が記述されている。operator="eq"は「等しい」という意味だ。
このように、Dataverseの内部構造、特にテーブル間の関連付けを正確に理解することで、システムエンジニアはアプリケーションの深い部分にアクセスし、必要な情報をピンポイントで取得できるようになる。たとえ直接的な1対1の関係ではない複雑な構造であっても、中間テーブルの役割を把握し、適切なクエリを組み立てることで、目的を達成できる。この知識は、Dataverseベースのシステム開発や運用、トラブルシューティングにおいて非常に価値のあるスキルとなるだろう。Dataverseの柔軟なデータモデルを最大限に活用するためにも、このような内部的な仕組みの理解は不可欠だ。