Мультиарендность в Power BI Embedded

У меня есть мультитенантное веб-приложение, и я использую подход базы данных для каждого клиента. Веб-приложение также будет использовать Power BI Embedded для отображения отчетов на основе данных для этого конкретного клиента, и все отчеты для каждого клиента будут иметь одинаковый формат, но источник данных будет другим.

Из того, что я видел, нет простого способа реализовать мультитенантность в Power BI, такого как передача источника данных в качестве параметра. Мне удалось найти два способа сделать Power BI встроенным мультитенантным. Либо используйте защиту на уровне строк, что будет означать, что мне нужно иметь единое хранилище данных для всех данных клиента, и это не вариант для меня. Другой вариант - иметь рабочее пространство на каждого арендатора.

Для второго варианта у меня было бы рабочее пространство шаблона, из которого будет создаваться копия для каждого нового клиента. В этом руководстве описано, как это сделать: https://powerbi.microsoft.com/fr-fr/blog/duplicate-workspaces-using-the-power-bi-rest-apis-a-step-пошаговоеруководство/.

Можно ли сделать то же самое с помощью пакета SDK Power BI C #? Мне также нужно будет изменить источник данных, используемый для каждой рабочей области. Как я могу сделать это для всех отчетов в моей рабочей области?

Наконец, открыл ли кто-нибудь более простой способ реализации мультитенантности со встроенным Power BI, или это так?


person anonuser1    schedule 30.10.2019    source источник


Ответы (1)


Это зависит от типа вашего источника данных (SQL Server, SSAS, файлы CSV и т. Д.) И режима подключения к данным (импорт, прямой запрос и т. Д.). Если вы можете использовать параметры, то один из вариантов - разрешить вновь клонированному отчету самим переключать источник данных с помощью параметры подключения. Для этого откройте Power Query Editor, щелкнув Edit Queries и в Manage Parameters определите два новых текстовых параметра, назовите их ServerName и DatabaseName:

введите описание изображения здесь

введите описание изображения здесь

Задайте их текущие значения, чтобы они указывали на один из ваших источников данных, например SQLSERVER2016 и AdventureWorks2016. Затем щелкните правой кнопкой мыши свой запрос в отчете и откройте Advanced Editor. Найдите имя сервера и имя базы данных в M-коде:

введите описание изображения здесь

и замените их параметрами, определенными выше, поэтому M-код будет выглядеть так:

введите описание изображения здесь

Теперь вы можете закрыть и применить изменения, и ваш отчет должен работать как раньше. Но теперь, когда вы хотите изменить источник данных, сделайте это с помощью Edit Parameters:

введите описание изображения здесь

и измените имя сервера и / или базы данных, чтобы указать на другой источник данных, который вы хотите использовать для своего отчета:

введите описание изображения здесь

После изменения значений параметров Power BI Desktop попросит вас применить изменения и перезагрузить данные из нового источника данных. Чтобы изменить значения параметров (т. Е. Источник данных) отчета, опубликованного в службе Power BI, перейдите в настройки набора данных и введите новое имя сервера и / или базы данных (также проверьте настройки шлюза, если это локальный источник данных):

введите описание изображения здесь

После изменения источника данных обновите набор данных, чтобы получить данные из нового источника данных. С учетной записью Power BI Pro вы можете делать это 8 раз в 24 часа, а если набор данных находится в выделенной емкости, этот предел повышается до 48 раз в 24 часа.

Чтобы сделать это программно, используйте Update Parameters / Update Parameters In Group и _ 12_ / _ 13_ Вызовы REST API. Например, вы можете сделать это с помощью PowerShell следующим образом:

Import-Module MicrosoftPowerBIMgmt
Import-Module MicrosoftPowerBIMgmt.Profile

$password = "xxxxx" | ConvertTo-SecureString -asPlainText -Force
$username = "[email protected]" 
$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 = "[email protected]" 
$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 Client:

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("[email protected], "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;
    }
}       
person Andrey Nikolov    schedule 30.10.2019
comment
Благодарим за исчерпывающий ответ. Могут ли при использовании этого метода два пользователя (из двух разных клиентов) получить доступ к своим базам данных при одновременном доступе к одному и тому же отчету? Есть ли способ связать параметры как часть встроенного компонента power bi? - person AleX_; 18.05.2021
comment
@AleX_ Параметры относятся к отчету / набору данных, а не к каждому пользователю. Все пользователи, просматривающие один отчет, увидят одни и те же данные. Вам потребуются отдельные экземпляры отчета для каждого пользователя или, по крайней мере, отдельные наборы данных (которые можно комбинировать с динамическое связывание, например). В противном случае вы должны объединить все данные из всех источников в единый набор данных и отфильтровать данные на основе текущего пользователя (также отметьте Безопасность на уровне строк). - person Andrey Nikolov; 18.05.2021