我有一个多租户Web应用程序,并且我正在使用每个租户方法的数据库。该Web应用程序还将使用Power BI Embedded来显示基于该特定租户的数据的报告,并且每个租户的所有报告将具有相同的格式,但是数据源将不同。
据我所见,没有在Power BI中实现多租户的直接方法,例如将数据源作为参数传递。我设法找到了两种方法来制作Power BI嵌入式多租户。使用行级安全性都意味着我需要为所有租户的数据提供一个数据仓库,这对我来说不是一个选择。另一个选择是每个租户都有一个工作区。
对于第二个选项,我将有一个模板工作区,将从中为每个新租户创建一个副本。本教程在此介绍如何执行此操作:https://powerbi.microsoft.com/fr-fr/blog/duplicate-workspaces-using-the-power-bi-rest-apis-a-step-by-step-tutorial/。
可以通过Power BI C#SDK进行相同的操作吗?我还需要更改每个工作区使用的数据源。如何为我的工作区中的所有报告执行此操作?
最后,有人发现了一种更简单的方法来实现嵌入式Power BI的多租户,还是这样吗?
取决于您的数据源类型(SQL Server,SSAS,CSV文件等)和数据连接模式(导入,直接查询等)。如果可以使用参数,那么您的选择之一就是允许新克隆的报告使用connection specific parameters本身来切换其数据源。为此,请单击Power Query Editor
打开Edit Queries
,然后在Manage Parameters
中定义两个新的文本参数,将其命名为ServerName
和DatabaseName
:
将其当前值设置为指向您的数据源之一,例如SQLSERVER2016
和AdventureWorks2016
。然后右键单击报告中的查询,然后打开Advanced Editor
。在M代码中找到服务器名称和数据库名称:
并将它们替换为上面定义的参数,因此M代码将如下所示:
现在您可以关闭并应用更改,您的报告应该像以前一样工作。但是现在,当您想更改数据源时,请使用Edit Parameters
:
并更改服务器和/或数据库名称以指向要用于报告的其他数据源:
更改参数值后,Power BI Desktop将要求您应用更改并从新数据源重新加载数据。要更改在Power BI Service中发布的报表的参数值(即数据源),请转到数据集的设置并输入新的服务器和/或数据库名称(如果这是本地数据源,则还要检查网关设置):
更改数据源后,刷新数据集以从新数据源获取数据。使用Power BI Pro帐户,您可以每24小时执行8次此操作,而如果数据集具有专用容量,则该限制将提高到每24小时48次。
要以编程方式执行此操作,请使用Update Parameters
/ Update Parameters
和Update Parameters In Group
/Update Parameters In Group
REST API调用。例如,您可以使用PowerShell这样执行此操作:
Refresh Dataset
如果无法使用参数,例如与SSAS的实时连接,可以使用Refresh Dataset
REST API调用更改连接字符串。在PowerShell中,可以这样进行:
Refresh Dataset In Group
注意,您需要同时提供新旧服务器和数据库名称。
在C#中,即使没有Power BI客户端,您也可以以非常相似的方式进行相同操作:
Refresh Dataset In Group
使用Power BI C#客户端可以使您的生活更轻松,例如可以通过以下方式刷新报告:
Import-Module MicrosoftPowerBIMgmt
Import-Module MicrosoftPowerBIMgmt.Profile
$password = "xxxxx" | ConvertTo-SecureString -asPlainText -Force
$username = "xxxxx@yyyyy.com"
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
Connect-PowerBIServiceAccount -Credential $credential
Invoke-PowerBIRestMethod -Url 'groups/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/datasets/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/UpdateParameters' -Method Post -Body '{
"updateDetails": [
{
"name": "ServerName",
"newValue": "SQLSERVER2019"
},
{
"name": "DatabaseName",
"newValue": "AdventureWorks2019"
}
]
}'
Invoke-PowerBIRestMethod -Url 'groups/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/datasets/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/refreshes' -Method Post
Disconnect-PowerBIServiceAccount
调用API时,您需要提供访问令牌。要获取它,请使用Update Datasources In Group或Import-Module MicrosoftPowerBIMgmt
Import-Module MicrosoftPowerBIMgmt.Profile
$password = "xxxxx" | ConvertTo-SecureString -asPlainText -Force
$username = "xxxxx@yyyyy.com"
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
Connect-PowerBIServiceAccount -Credential $credential
Invoke-PowerBIRestMethod -Url 'groups/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/datasets/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Default.UpdateDatasources' -Method Post -Body '{
"updateDetails": [
{
"datasourceSelector": {
"datasourceType": "AnalysisServices",
"connectionDetails": {
"server": "My-As-Server",
"database": "My-As-Database"
}
},
"connectionDetails": {
"server": "New-As-Server",
"database": "New-As-Database"
}
}
]
}'
Disconnect-PowerBIServiceAccount
库,例如使用这样的代码:
var group_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var dataset_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var restUrlUpdateParameters = $"https://api.powerbi.com/v1.0/myorg/groups/{group_id}/datasets/{dataset_id}/Default.UpdateParameters";
var postData = new { updateDetails = new[] { new { name = "ServerName", newValue = "NEWSERVER" }, new { name = "DatabaseName", newValue = "Another_AdventureWorks2016" } } };
var responseUpdate = client.PostAsync(restUrlUpdateParameters, new StringContent(JsonConvert.SerializeObject(postData), Encoding.UTF8, "application/json")).Result;
var restUrlRefreshDataset = $"https://api.powerbi.com/v1.0/myorg/groups/{group_id}/datasets/{dataset_id}/refreshes";
var responseRefresh = client.PostAsync(restUrlRefreshDataset, null).Result;