当前位置: 首页 > 知识库问答 >
问题:

Power BI嵌入式中的多租户

仇和蔼
2023-03-14

我有一个多租户的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来实现多租户,或者是这样?

共有1个答案

邓嘉致
2023-03-14

这取决于您的数据源类型(SQL Server、SSAS、CSV文件等)和数据连接模式(导入、直接查询等)。如果可以使用参数,那么其中一个选项是允许新克隆的报表通过使用特定于连接的参数来切换其数据源本身。为此,通过单击Edit querys打开Power Query Editor,并在Manage Parameters中定义两个新的文本参数,将它们命名为ServerNameDatabaseName

将其当前值设置为指向您的一个数据源,例如SQLSERVER2016AdventureWorks2016。然后右键单击报告中的查询并打开高级编辑器。在M代码中查找服务器名称和数据库名称:

并用上面定义的参数替换它们,因此M代码如下所示:

现在,您可以关闭和应用更改,您的报告应该像以前一样工作。但是现在,当您想要更改数据源时,请使用Edit Parameters进行更改:

并将服务器和/或数据库名称更改为指向要用于报表的其他数据源:

更改参数值后,Power BI Desktop将要求您应用更改并从新数据源重新加载数据。要更改在Power BI服务中发布的报告的参数值(即数据源),请转到数据集的设置,并输入新的服务器和/或数据库名称(如果这是本地数据源,也请检查网关设置):

更改数据源后,刷新数据集以从新数据源获取数据。使用Power BI Pro帐户,您可以每24小时执行8次,而如果数据集具有专用容量,则此限制将提高到每24小时48次。

要以编程方式执行此操作,请使用组中的更新参数/和组中的刷新数据集/刷新数据集REST API调用。例如,您可以使用PowerShell这样做:

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

如果不能使用参数,例如:实时连接到SSAS,可以使用更新数据源组中的REST API调用更改连接字符串。在PowerShell中,可以这样做:

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

请注意,您需要提供新旧服务器和数据库名称。

在C#中,即使没有Power BI客户端,您也可以以非常相似的方式执行相同的操作:

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;

使用Power BI C#客户端可以让您的生活更轻松,例如,可以通过以下方式刷新报告:

var group_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var dataset_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var credentials = new TokenCredentials(accessToken, "Bearer");

using (var client = new PowerBIClient(new Uri("https://api.powerbi.com"), credentials))
{
    client.Datasets.RefreshDatasetInGroup(group_id, dataset_id);
}

调用API时,需要提供访问令牌。要获取它,请使用ADAL或MSAL库,例如使用如下代码:

private static string resourceUri = "https://analysis.windows.net/powerbi/api";
private static string authorityUri = "https://login.windows.net/common/"; // It was https://login.windows.net/common/oauth2/authorize in prior versions
private static string clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // Register at https://dev.powerbi.com/apps
private static string groupId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
private static string reportId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

private static AuthenticationContext authContext = new AuthenticationContext(authorityUri, new TokenCache());


public string Authenticate()
{
    AuthenticationResult authenticationResult = null;

    // First check is there token in the cache
    try
    {
        authenticationResult = authContext.AcquireTokenSilentAsync(resourceUri, clientId).Result;
    }
    catch (AggregateException ex)
    {
        AdalException ex2 = ex.InnerException as AdalException;
        if ((ex2 == null) || (ex2 != null && ex2.ErrorCode != "failed_to_acquire_token_silently"))
        {
            MessageBox.Show(ex.Message);
            return;
        }
    }

    if (authenticationResult == null)
    {
        var uc = new UserPasswordCredential("user@example.com, "Strong password");
        try
        {
            authenticationResult = authContext.AcquireTokenAsync(resourceUri, clientId, uc).Result;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + ex.InnerException == null ? "" : Environment.NewLine + ex.InnerException.Message);
            return;
        }
    }

    if (authenticationResult == null)
        MessageBox.Show("Call failed.");
    else
    {
        return authenticationResult.AccessToken;
    }
}       

 类似资料:
  • 我正在构建一个应用程序,它应该服务于多个租户,并存储他们非常敏感的数据。每个租户都有多个用户。我的后端堆栈是用spring boot Hibernate5构建的。我希望hibernate处理多租户问题,所以我有两个问题要问专家: 如果我使用的是每租户模式范式,如何在登录时将用户名与租户关联?每个租户都有自己的用户表,那么我如何知道用户名属于哪个租户呢? 在注册时,什么是正确的方法来动态创建新模式?

  • 我的系统: Qt Embedded(开源版)4.8 用于图形的Linux帧缓冲区 字体:(拉丁语、日语、希腊语)。(/usr/lib/fonts) 我正在尝试将拉丁字母与其他类型的字符(例如日语)混合使用。我有拉丁字母和日语字符的字体,但它们不是同一种字体。我研究了帖子: Qt同时使用多个字体以及如何在Qt-embedded中正确输出多语言文本 我按照步骤操作,但无法正确显示所有字符 有没有办法表

  • 我在创建可以动态连接到多个数据库的spring boot应用程序时遇到问题,具体取决于用户输入。基本上,应用程序在不同的数据库上运行相同的sql查询。建模我的尝试在此之后,我收到以下错误: -- 配置类: 属性文件: 关于我如何实现这一点有什么想法吗?正如你所知,我对这种多数据库配置还不是非常精通。

  • 保护数据。 清除租户级别的旧数据。 到目前为止,我们的调查结果是,我们可以为每个租户使用单独的Redis实例--这对我们来说不是一个好的解决方案。 我们发现的另一个选项是用“tenant_id:”前缀命名密钥空间。这个选项解决了第一点--数据现在是安全的,但我们还有第二点需要解决。

  • 我有一个由3个节点组成的HDF集群,其中安装了Nifi。我的目标是在Nifi水平上实现多租户(也许不是最好的词)。意思是我想要两件事: null 任何帮助都很感激... 谢谢你的回答

  • 我目前正试图找出为我的系统设置多租户的最佳方法。我面临的问题是,租户并不总是必须是子域,但可以作为子域的一部分进行设置,子域可以有多个租户。我似乎在网上找不到任何东西可以帮助我在Laravel 6中进行设置。 系统要求: 一台服务器可以有许多子域 系统必须设置一个数据库,该数据库将使用tenant_id来确定哪些数据属于租户。 我目前正在以以下结构将所有子域数据存储在“subdomains”表中: