Power BI RDL 連接 Dataverse,為什麼 Shared Connection 卻要選 SQL Server?

| PowerPlatform | 1 Reads

在 Power BI Service 中為 Paginated Report(RDL)設定共用資料連線時,我遇到了一個乍看非常矛盾的問題:

資料明明存放在 Dataverse,Power BI 的「新しい接続」中也明明存在 Dataverse 這個連線類型,為什麼實際上卻需要選擇 SQL Server

進一步分析實際使用中的 RDL 後,原因終於明確了。

一、先說結論

如果現有 RDL 內部採用的是:

<DataProvider>SQLAZURE</DataProvider>

並且 Connection String 類似:

Data Source=[環境].crm.dynamics.com,5558;
Initial Catalog=[Database ID];
Encrypt=True;
Authentication=Active Directory Interactive;

同時 Dataset 中直接使用:

SELECT ...
FROM ...
INNER JOIN ...
WHERE ...
GROUP BY ...
UNION ALL ...

那麼這份 RDL 實際採用的架構就是:

RDL
 ↓
SQL / SQLAZURE Provider
 ↓
T-SQL
 ↓
Dataverse TDS Endpoint
 ↓
Dataverse

因此在 Power BI Service 中建立 Shareable Cloud Connection 時,應該匹配這個 RDL 的資料來源 Provider

接続の種類
→ SQL Server

而不是因為最終資料存在 Dataverse,就直接選:

接続の種類
→ Dataverse

二、Dataverse 為什麼可以用 SQL 查?

Dataverse 本身提供了 TDS Endpoint

TDS 是 Tabular Data Stream,也就是 SQL Server 所使用的通訊協議之一。

Dataverse 透過 TDS Endpoint 對外提供一個類似 SQL Server 的唯讀查詢介面,因此可以使用 SQL:

SELECT
    A.Column1,
    B.Column2,
    COUNT(*)
FROM TableA AS A
INNER JOIN TableB AS B
    ON A.Id = B.Id
WHERE ...
GROUP BY ...

所以從帳票製作者的角度,可以把 Dataverse 理解成:

「一個可以用 SQL 查詢的資料來源。」

這對 RDL 特別方便。


三、這不是 RDL 的固定預設

有一點需要特別注意:

並不是只要使用 RDL + Dataverse,就一定會自動變成 SQL Server 連線。

RDL 本身可以支援不同的 Data Source。

真正決定連線方式的是 RDL 裡面的設定,例如:

<DataProvider>SQLAZURE</DataProvider>

本次實際分析的 RDL 使用的就是 SQLAZURE

而它的 Data Source 名字雖然叫:

DataverseTDS

但這個名字本身沒有決定性。

例如:

<DataSource Name="DataverseTDS">

這只是開發者取的一個名稱。

就算改成:

<DataSource Name="ABC">

實際連線方式也不會因此改變。

真正重要的是:

<DataProvider>SQLAZURE</DataProvider>

四、為什麼當初會選擇 SQL/TDS?

主要原因是:

製作複雜 RDL 帳票時,SQL 非常方便。

例如一張帳票可能需要:

Table A
   ↓ JOIN
Table B
   ↓ JOIN
Master C
   ↓
日期條件
   ↓
組織條件
   ↓
GROUP BY
   ↓
COUNT

使用 SQL 可以很自然地寫成:

SELECT ...
FROM A
INNER JOIN B ...
INNER JOIN C ...
WHERE ...
GROUP BY ...

甚至還可以使用:

DISTINCT
TOP
COUNT
DATEADD
NOT EXISTS
UNION ALL

本次分析的實際 RDL 中,就存在大量這類 SQL。

因此對這類「統計帳票」而言:

Dataverse
    ↓
TDS Endpoint
    ↓
SQL
    ↓
RDL

是一種非常自然的設計。

換句話說,並不是 Dataverse 強迫 RDL 使用 SQL。

而是:

為了方便使用 SQL 製作 RDL Dataset,因此選擇了 Dataverse TDS Endpoint。


五、那 Power BI 裡的「Dataverse」Connection 又是什麼?

Power BI Service 建立新 Connection 時,可以看到:

接続の種類
├─ Dataverse
├─ SQL Server
├─ ...

這裡的 Dataverse 是另一種資料來源 Connector。

例如它要求填寫:

環境のドメイン

xxxx.crm.dynamics.com

它代表的是:

RDL / Power BI
 ↓
Dataverse Connector
 ↓
Dataverse

而目前這批 RDL 使用的是:

RDL
 ↓
SQL Provider
 ↓
Dataverse TDS
 ↓
Dataverse

兩者最終都到 Dataverse,但中間的 Provider 完全不同

可以理解為:

項目 SQL/TDS 方式 Dataverse Connector
最終資料來源 Dataverse Dataverse
RDL Provider SQL / SQLAZURE Dataverse 對應 Provider
查詢方式 SQL Dataverse Connector 對應方式
TDS Endpoint 使用 不以現有 SQL DataSource 形式使用
現有 SQL Dataset 可直接使用 不能直接沿用

六、為什麼不能直接把 Connection Type 改成 Dataverse?

因為 Power BI Service 的 Shared Connection 並不會幫忙「翻譯 Dataset」。

目前 RDL 裡已經寫的是:

SELECT ...
FROM ...
INNER JOIN ...
GROUP BY ...

Power BI 不會因為把:

SQL Server

改成:

Dataverse

就自動把這些 SQL:

SQL
 ↓
自動轉換
 ↓
Dataverse Query

不存在這樣的自動轉換。

Shared Connection 主要負責的是:

這個已經定義好的 Data Source,要使用哪條實際連線以及哪套 Credential。

它不是 Dataset Query Converter。


七、所以現有 RDL 不修改的話,目前應該怎麼設定?

以這次實際分析的 RDL 為例:

<DataProvider>SQLAZURE</DataProvider>

Connection String 又是:

Data Source=[Dataverse Environment],5558;
Initial Catalog=[Database];

因此 Power BI Service 裡應建立類似:

接続名:
開発環境_DataverseTDS

接続の種類:
SQL Server

Server:
[環境].crm.dynamics.com,5558

Database:
[Database ID]

認証:
OAuth 2.0

然後:

RDL
 ↓
ゲートウェイとクラウド接続
 ↓
Map to
 ↓
這條 Shared Cloud Connection

這樣就可以讓多份 RDL 共用同一套 Connection / Credential。


八、SQLAZURE 和 Power BI 裡的 SQL Server 為什麼名字又不一樣?

這也是很容易搞混的一點。

RDL XML 中可能看到:

<DataProvider>SQLAZURE</DataProvider>

而 Power BI Service 建立 Connection 時看到的卻是:

SQL Server

這兩個畫面的命名層次不同。

可以簡單理解成:

RDL XML
SQLAZURE
      ↓
SQL 系 Data Provider

Power BI Service
SQL Server
      ↓
可供這類 SQL Data Source 映射的 Cloud Connection

所以不能要求兩邊的顯示名稱必須完全一致。

真正應該確認的是:

  • RDL 的 DataProvider

  • Connection String

  • Server

  • Database

  • Dataset 使用的 Query Language


九、如果真的想改成「Dataverse」Connection 呢?

可以,但那就不是單純修改一個下拉框了。

需要重新設計 RDL 的資料取得層。

也就是從現在的:

RDL
 ↓
SQLAZURE
 ↓
SQL
 ↓
Dataverse TDS

改成另一種 Data Source,例如:

RDL
 ↓
Dataverse / Power Query
 ↓
Dataverse

這時原有的 SQL:

SELECT
JOIN
GROUP BY
UNION
...

通常也需要重新實作。

例如使用 Power Query 時,對應的是 M 語言

這裡需要特別注意:

不是 Power Fx。

Power Fx 主要是 Canvas App 等 Power Platform 場景使用的公式語言。

Paginated Report 如果改成 Power Query 型 Dataset,主要涉及的是:

Power Query
→ M

而不是:

Power Fx

十、是否值得把現有 RDL 全部改成 Dataverse Connector?

如果現有 RDL 已經大量使用:

JOIN
GROUP BY
COUNT
UNION
DATEADD
DISTINCT
NOT EXISTS

那通常沒有必要僅僅因為:

「資料本來就是 Dataverse」

就把 Data Source 全部重做。

因為 Dataverse TDS Endpoint 本來就是 Dataverse 官方提供的資料存取方式。

對大量既存 SQL 帳票而言:

保留 SQL/TDS
+
統一使用 Shared Cloud Connection

通常比重新改寫所有 Dataset 要簡單得多。


最容易搞混的四個概念

最後可以把整件事濃縮成這張表:

層級 本次實際情況
資料真正存在哪裡 Dataverse
怎麼讓外部查詢 Dataverse TDS Endpoint
RDL 使用什麼 Provider SQLAZURE
Power BI Shared Connection SQL Server

因此這四句話可以同時成立:

資料是 Dataverse。
使用 Dataverse TDS Endpoint。
RDL 使用 SQLAZURE。
Power BI Connection 選 SQL Server。

它們並不矛盾。

最終結論

判斷 Power BI Paginated Report 應該使用哪一種 Shared Connection,不要只看資料最終存在哪裡

應該優先查看 RDL 本身:

DataProvider 是什麼?
Connection String 是什麼?
Dataset 寫的是什麼查詢?

如果現有 RDL 是:

SQLAZURE
+
Dataverse :5558
+
T-SQL Dataset

那麼它本質上就是:

透過 SQL/TDS 查詢 Dataverse 的 RDL。

在不修改 RDL 的前提下,Power BI Service 裡應該繼續使用 SQL Server 類型的 Shared Cloud Connection

Dataverse Connection 雖然存在,卻是另一條資料存取路徑,不能靠修改 Connection Type 就直接替換現有 SQL/TDS RDL

This article was last edited at