Driver do Microsoft ADO.NET para a Engenharia de Dados do Microsoft Fabric (versão prévia)

Importante

Esse recurso está na versão prévia.

ADO.NET é uma tecnologia de acesso a dados amplamente adotada no ecossistema do .NET que permite que os aplicativos se conectem e trabalhem com dados de bancos de dados e plataformas de Big Data.

O Microsoft ADO.NET Driver for Fabric Data Engineering permite que você se conecte, consulte e gerencie cargas de trabalho do Spark no Microsoft Fabric com a confiabilidade e a simplicidade dos padrões de ADO.NET padrão. Baseado nas APIs Livy do Microsoft Fabric, o driver fornece conectividade segura e flexível do Spark SQL para seus aplicativos .NET, usando abstrações familiares DbConnection, DbCommand e DbDataReader.

Características principais

  • ADO.NET Compatível: implementação completa de abstrações ADO.NET (DbConnection, , DbCommand, DbDataReader, DbParameter) DbProviderFactory
  • Autenticação de Identidade do Microsoft Entra: múltiplos fluxos de autenticação incluindo CLI do Azure, navegador interativo, credenciais de cliente, baseada em certificado e autenticação de token de acesso.
  • Suporte à consulta nativa do Spark SQL: execução direta de instruções SQL do Spark com consultas parametrizadas
  • Suporte a tipos de dados abrangentes: suporte para todos os tipos de dados SQL do Spark, incluindo tipos complexos (ARRAY, MAP, STRUCT)
  • Agrupamento de Conexões: gerenciamento interno do pool de conexões para melhorar o desempenho
  • Reutilização da sessão: gerenciamento eficiente de sessão do Spark para reduzir a latência de inicialização
  • Pré-busca assíncrona: carregamento de dados em segundo plano para melhorar o desempenho com grandes conjuntos de resultados
  • Reconexão automática: recuperação automática de sessão após falhas de conexão

Observação

No Apache Spark de software livre, o banco de dados e o esquema são usados sinônimos. Por exemplo, a execução SHOW SCHEMAS ou SHOW DATABASES em um Bloco de Anotações do Fabric retorna o mesmo resultado – uma lista de todos os esquemas no Lakehouse.

Pré-requisitos

Antes de usar o Microsoft ADO.NET Driver for Microsoft Fabric Data Engineering, verifique se você tem:

  • Runtime do .NET: .NET 8.0 ou posterior
  • Microsoft Fabric Access: acesso a um workspace do Microsoft Fabric com recursos de Engenharia de Dados
  • Credenciais de ID do Azure Entra: credenciais apropriadas para autenticação
  • IDs do Workspace e Lakehouse: identificadores GUID para o seu Workspace do Fabric e Lakehouse
  • CLI do Azure (opcional): necessário para o método de autenticação da CLI do Azure

Baixar, incluir, fazer referência e verificar

Baixar o pacote NuGet

O Microsoft ADO.NET Driver for Microsoft Fabric Data Engineering versão 1.0.0 está em versão prévia pública que você pode baixar nesses links do centro de download.

Fazer referência ao pacote NuGet em seu projeto

Inclua o pacote NuGet baixado em seu projeto e adicione uma referência do pacote ao arquivo de projeto:

<ItemGroup>
    <PackageReference Include="Microsoft.Spark.Livy.AdoNet" Version="1.0.0" />
</ItemGroup>

Verifique a instalação

Após a inclusão e a referência, verifique se o pacote está disponível em seu projeto:

using Microsoft.Spark.Livy.AdoNet;

// Verify the provider is registered
var factory = LivyProviderFactory.Instance;
Console.WriteLine($"Provider: {factory.GetType().Name}");

Exemplo de início rápido

using Microsoft.Spark.Livy.AdoNet;

// Connection string with required parameters
string connectionString =
    "Server=https://api.fabric.microsoft.com/v1;" +
    "SparkServerType=Fabric;" +
    "FabricWorkspaceID=<workspace-id>;" +
    "FabricLakehouseID=<lakehouse-id>;" +
    "AuthFlow=AzureCli;";

// Create and open connection
using var connection = new LivyConnection(connectionString);
await connection.OpenAsync();

Console.WriteLine("Connected successfully!");

// Execute a query
using var command = connection.CreateCommand();
command.CommandText = "SELECT 'Hello from Fabric!' as message";

using var reader = await command.ExecuteReaderAsync();
if (await reader.ReadAsync())
{
    Console.WriteLine(reader.GetString(0));
}

Formato da cadeia de conexão

Formato básico

O Microsoft ADO.NET Driver usa o formato de cadeia de conexão de ADO.NET padrão:

Parameter1=Value1;Parameter2=Value2;...

Parâmetros necessários

Parâmetro Descrição Exemplo
Server Ponto de extremidade da API do Microsoft Fabric https://api.fabric.microsoft.com/v1
SparkServerType Identificador de tipo de servidor Fabric
FabricWorkspaceID Identificador de workspace do Microsoft Fabric (GUID) <workspace-id>
FabricLakehouseID Identificador do Microsoft Fabric Lakehouse (GUID) <lakehouse-id>
AuthFlow Método de autenticação AzureCli, BrowserBased, ClientSecretCredential, ClientCertificateCredential, AuthAccessToken, , FileToken

Parâmetros opcionais

Configurações de conexão

Parâmetro Tipo Default Descrição
LivySessionTimeoutSeconds Integer 60 Tempo em segundos para aguardar a criação da sessão
LivyStatementTimeoutSeconds Integer 600 Tempo em segundos para aguardar a execução do comando
SessionName String (auto) Nome personalizado para a sessão do Spark
AutoReconnect booleano false Habilitar a recuperação automática de sessão

Configurações do pool de conexões

Parâmetro Tipo Default Descrição
ConnectionPoolEnabled booleano true Habilitar o pool de conexões
MinPoolSize Integer 1 Conexões mínimas no pool
MaxPoolSize Integer 20 Máximo de conexões no pool
ConnectionMaxIdleTimeMs Integer 1800000 Tempo máximo de ociosidade antes da conexão ser reciclada (30 min)
MaxLifetimeMs Integer 3600000 Tempo de vida máximo de uma conexão em pool (60 min)
ValidateConnections booleano true Validar conexões antes do uso
ValidationTimeoutMs Integer 5000 Tempo limite para validação de conexão

Configurações de registro em log

Parâmetro Tipo Default Descrição
LogLevel String Information Nível de log: Trace, Debug, Information, Warning, Error
LogFilePath String (nenhuma) Caminho para registro de logs baseado em arquivo

Observação

Aliases entre drivers: O driver aceita nomes de propriedade JDBC e ODBC, além de nomes de ADO.NET nativos (por exemplo, WorkspaceId mapeia para FabricWorkspaceID, mapeia LakehouseId para FabricLakehouseID). Todos os nomes de propriedade não diferenciam maiúsculas de minúsculas.

Cadeias de conexão de exemplo

Conexão básica (autenticação da CLI do Azure)

Server=https://api.fabric.microsoft.com/v1;SparkServerType=Fabric;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=AzureCli

Com opções de pool de conexões

Server=https://api.fabric.microsoft.com/v1;SparkServerType=Fabric;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=AzureCli;ConnectionPoolEnabled=true;MinPoolSize=2;MaxPoolSize=10

Com reconexão automática e registro em log

Server=https://api.fabric.microsoft.com/v1;SparkServerType=Fabric;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=AzureCli;AutoReconnect=true;LogLevel=Debug

Autenticação

O Microsoft ADO.NET Driver dá suporte a vários métodos de autenticação por meio da ID do Microsoft Entra (antigo Azure Active Directory). A autenticação é configurada usando o AuthFlow parâmetro na cadeia de conexão.

Métodos de autenticação

Valor do AuthFlow Descrição Mais Adequado Para
AzureCli Usa credenciais armazenadas em cache da CLI do Azure Desenvolvimento e teste
BrowserBased Autenticação interativa baseada em navegador Aplicativos voltados para o usuário
ClientSecretCredential Entidade de serviço com segredo do cliente Serviços automatizados, trabalhos em segundo plano
ClientCertificateCredential Principal de serviço com certificado Aplicativos empresariais
AuthAccessToken Token de acesso do portador pré-adquirido Cenários de autenticação personalizados

Autenticação da CLI do Azure

Melhor para: Desenvolvimento e teste

string connectionString =
    "Server=https://api.fabric.microsoft.com/v1;" +
    "SparkServerType=Fabric;" +
    "FabricWorkspaceID=<workspace-id>;" +
    "FabricLakehouseID=<lakehouse-id>;" +
    "AuthFlow=AzureCli;";

using var connection = new LivyConnection(connectionString);
await connection.OpenAsync();

Pré-requisitos:

  • CLI do Azure instalada: az --version
  • Conectado: az login

Autenticação interativa do navegador

Melhor para: aplicativos voltados para o usuário

string connectionString =
    "Server=https://api.fabric.microsoft.com/v1;" +
    "SparkServerType=Fabric;" +
    "FabricWorkspaceID=<workspace-id>;" +
    "FabricLakehouseID=<lakehouse-id>;" +
    "AuthFlow=BrowserBased;" +
    "AuthTenantID=<tenant-id>;";

using var connection = new LivyConnection(connectionString);
await connection.OpenAsync(); // Opens browser for authentication

Comportamento:

  • Abre uma janela do navegador para autenticação do usuário
  • As credenciais são armazenadas em cache para conexões subsequentes

Autenticação de credenciais do cliente (principal de serviço)

Melhor para: serviços automatizados e trabalhos em segundo plano

string connectionString =
    "Server=https://api.fabric.microsoft.com/v1;" +
    "SparkServerType=Fabric;" +
    "FabricWorkspaceID=<workspace-id>;" +
    "FabricLakehouseID=<lakehouse-id>;" +
    "AuthFlow=ClientSecretCredential;" +
    "AuthTenantID=<tenant-id>;" +
    "AuthClientID=<client-id>;" +
    "AuthClientSecret=<client-secret>;";

using var connection = new LivyConnection(connectionString);
await connection.OpenAsync();

Parâmetros necessários:

  • AuthTenantID: ID do locatário do Azure
  • AuthClientID: ID do aplicativo (cliente) da Microsoft Entra ID
  • AuthClientSecret: segredo do cliente do Microsoft Entra ID

Autenticação baseada em certificado

Melhor para: aplicativos empresariais que exigem autenticação baseada em certificado

string connectionString =
    "Server=https://api.fabric.microsoft.com/v1;" +
    "SparkServerType=Fabric;" +
    "FabricWorkspaceID=<workspace-id>;" +
    "FabricLakehouseID=<lakehouse-id>;" +
    "AuthFlow=ClientCertificateCredential;" +
    "AuthTenantID=<tenant-id>;" +
    "AuthClientID=<client-id>;" +
    "AuthCertificatePath=C:\\certs\\mycert.pfx;" +
    "AuthCertificatePassword=<password>;";

using var connection = new LivyConnection(connectionString);
await connection.OpenAsync();

Parâmetros necessários:

  • AuthTenantID: ID do locatário do Azure
  • AuthClientID: ID do aplicativo (cliente)
  • AuthCertificatePath: caminho para o arquivo de certificado PFX/PKCS12
  • AuthCertificatePassword: senha do certificado

Autenticação de token de acesso

Melhor para: cenários de autenticação personalizados

// Acquire token through your custom mechanism
string accessToken = await AcquireTokenFromCustomSourceAsync();

string connectionString =
    "Server=https://api.fabric.microsoft.com/v1;" +
    "SparkServerType=Fabric;" +
    "FabricWorkspaceID=<workspace-id>;" +
    "FabricLakehouseID=<lakehouse-id>;" +
    "AuthFlow=AuthAccessToken;" +
    $"AuthAccessToken={accessToken};";

using var connection = new LivyConnection(connectionString);
await connection.OpenAsync();

Observação

É altamente recomendável evitar credenciais de codificação rígida, como senhas, chaves, segredos, tokens ou certificados em seu código. Em vez disso, use o Azure Key Vault para armazenar com segurança esses valores e recuperá-los em runtime.

Exemplos de uso

Conexão e consulta básicas

using Microsoft.Spark.Livy.AdoNet;

string connectionString =
    "Server=https://api.fabric.microsoft.com/v1;" +
    "SparkServerType=Fabric;" +
    "FabricWorkspaceID=<workspace-id>;" +
    "FabricLakehouseID=<lakehouse-id>;" +
    "AuthFlow=AzureCli;";

using var connection = new LivyConnection(connectionString);
await connection.OpenAsync();

Console.WriteLine($"Connected! Server version: {connection.ServerVersion}");

// Execute a query
using var command = connection.CreateCommand();
command.CommandText = "SELECT * FROM employees LIMIT 10";

using var reader = await command.ExecuteReaderAsync();

// Print column names
for (int i = 0; i < reader.FieldCount; i++)
{
    Console.Write($"{reader.GetName(i)}\t");
}
Console.WriteLine();

// Print rows
while (await reader.ReadAsync())
{
    for (int i = 0; i < reader.FieldCount; i++)
    {
        Console.Write($"{reader.GetValue(i)}\t");
    }
    Console.WriteLine();
}

Consultas parametrizadas

using var command = connection.CreateCommand();
command.CommandText = "SELECT * FROM orders WHERE order_date >= @startDate AND status = @status";

// Add parameters
command.Parameters.AddWithValue("@startDate", new DateTime(2024, 1, 1));
command.Parameters.AddWithValue("@status", "completed");

using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
    Console.WriteLine($"Order: {reader["order_id"]}, Total: {reader["total"]:C}");
}

ExecuteScalar para valores únicos

using var command = connection.CreateCommand();
command.CommandText = "SELECT COUNT(*) FROM customers";

var count = await command.ExecuteScalarAsync();
Console.WriteLine($"Total customers: {count}");

ExecuteNonQuery para as operações DML

// INSERT
using var insertCommand = connection.CreateCommand();
insertCommand.CommandText = @"
    INSERT INTO employees (id, name, department, salary)
    VALUES (100, 'John Doe', 'Engineering', 85000)";

int rowsAffected = await insertCommand.ExecuteNonQueryAsync();
Console.WriteLine($"Inserted {rowsAffected} row(s)");

// UPDATE
using var updateCommand = connection.CreateCommand();
updateCommand.CommandText = "UPDATE employees SET salary = 90000 WHERE id = 100";

rowsAffected = await updateCommand.ExecuteNonQueryAsync();
Console.WriteLine($"Updated {rowsAffected} row(s)");

// DELETE
using var deleteCommand = connection.CreateCommand();
deleteCommand.CommandText = "DELETE FROM employees WHERE id = 100";

rowsAffected = await deleteCommand.ExecuteNonQueryAsync();
Console.WriteLine($"Deleted {rowsAffected} row(s)");

Trabalhando com grandes conjuntos de resultados

using var command = connection.CreateCommand();
command.CommandText = "SELECT * FROM large_table";

using var reader = await command.ExecuteReaderAsync();

int rowCount = 0;
while (await reader.ReadAsync())
{
    // Process each row
    ProcessRow(reader);
    rowCount++;

    if (rowCount % 10000 == 0)
    {
        Console.WriteLine($"Processed {rowCount} rows...");
    }
}

Console.WriteLine($"Total rows processed: {rowCount}");

Descoberta de esquema

// List all tables
using var showTablesCommand = connection.CreateCommand();
showTablesCommand.CommandText = "SHOW TABLES";

using var tablesReader = await showTablesCommand.ExecuteReaderAsync();
Console.WriteLine("Available tables:");
while (await tablesReader.ReadAsync())
{
    Console.WriteLine($"  {tablesReader.GetString(0)}");
}

// Describe table structure
using var describeCommand = connection.CreateCommand();
describeCommand.CommandText = "DESCRIBE employees";

using var schemaReader = await describeCommand.ExecuteReaderAsync();
Console.WriteLine("\nTable structure for 'employees':");
while (await schemaReader.ReadAsync())
{
    Console.WriteLine($"  {schemaReader["col_name"]}: {schemaReader["data_type"]}");
}

Usando LivyConnectionStringBuilder

using Microsoft.Spark.Livy.AdoNet;

var builder = new LivyConnectionStringBuilder
{
    Server = "https://api.fabric.microsoft.com/v1",
    SparkServerType = "Fabric",
    FabricWorkspaceID = "<workspace-id>",
    FabricLakehouseID = "<lakehouse-id>",
    AuthFlow = "AzureCli",
    ConnectionPoolingEnabled = true,
    MinPoolSize = 2,
    MaxPoolSize = 10,
    ConnectionTimeout = 60
};

using var connection = new LivyConnection(builder.ConnectionString);
await connection.OpenAsync();

Usando DbProviderFactory

using System.Data.Common;
using Microsoft.Spark.Livy.AdoNet;

// Register the provider factory (typically done at application startup)
DbProviderFactories.RegisterFactory("Microsoft.Spark.Livy.AdoNet", LivyProviderFactory.Instance);

// Create connection using factory
var factory = DbProviderFactories.GetFactory("Microsoft.Spark.Livy.AdoNet");

using var connection = factory.CreateConnection();
connection.ConnectionString = connectionString;

await connection.OpenAsync();

using var command = factory.CreateCommand();
command.Connection = connection;
command.CommandText = "SELECT * FROM employees LIMIT 5";

using var reader = await command.ExecuteReaderAsync();
// Process results...

Mapeamento de tipo de dados

O driver mapeia tipos de dados SQL do Spark para tipos .NET:

Tipo SQL do Spark Tipo de .NET DbType
BOOLEAN bool booleano
TINYINT sbyte SByte
SMALLINT short Int16
INT int Int32
BIGINT long Int64
FLOAT float Solteiro
DUPLO double Double
DECIMAL(p,s) decimal Decimal
STRING string String
VARCHAR(n) string String
CHAR(n) string String
BINÁRIO byte[] Binário
DATE DateTime Date
TIMESTAMP DateTime Data e hora
MATRIZ<T> T[] ou string (JSON) Objeto
MAP<K,V> Dictionary<K,V> ou string (JSON) Objeto
STRUCT object ou string (JSON) Objeto

Trabalhando com tipos complexos

Tipos complexos (ARRAY, MAP, STRUCT) são retornados como cadeias de caracteres JSON por padrão:

using System.Text.Json;
using System.Collections.Generic;

using var command = connection.CreateCommand();
command.CommandText = "SELECT array_column, map_column, struct_column FROM complex_table LIMIT 1";

using var reader = await command.ExecuteReaderAsync();
if (await reader.ReadAsync())
{
    // Complex types returned as JSON strings
    string arrayJson = reader.GetString(0);  // e.g., "[1, 2, 3]"
    string mapJson = reader.GetString(1);    // e.g., "{\"key\": \"value\"}"
    string structJson = reader.GetString(2); // e.g., "{\"field1\": 1, \"field2\": \"text\"}"

    // Parse with System.Text.Json
    var array = JsonSerializer.Deserialize<int[]>(arrayJson);
    var map = JsonSerializer.Deserialize<Dictionary<string, string>>(mapJson);
}

Solução de problemas

Esta seção fornece diretrizes para resolver problemas comuns que você pode encontrar ao usar o Microsoft ADO.NET Driver for Microsoft Fabric Data Engineering.

Problemas comuns

As seções a seguir descrevem problemas comuns e suas soluções:

Falhas na conexão

Problema: não é possível se conectar ao Microsoft Fabric

Soluções:

  1. Verifique FabricWorkspaceID e FabricLakehouseID são GUIDs corretos
  2. Verifique a autenticação da CLI do Azure: az account show
  3. Verifique se você tem permissões de workspace apropriadas do Fabric
  4. Verificar a conectividade de rede para api.fabric.microsoft.com

Erros de autenticação

Problema: a autenticação falha com a CLI do Azure

Soluções:

  • Executar az login para atualizar credenciais
  • Verifique o locatário correto: az account set --subscription <subscription-id>
  • Verificar a validade do token: az account get-access-token --resource https://api.fabric.microsoft.com

Tempos limite da consulta

Problema: consultas estão atingindo o tempo limite em tabelas grandes

Soluções:

  • Aumentar o tempo limite da instrução: LivyStatementTimeoutSeconds=300
  • Usar LIMIT cláusula para restringir o tamanho do resultado durante o desenvolvimento
  • Verifique se o cluster Spark tem recursos adequados

Tempo limite de criação de sessão

Problema: a conexão atinge o tempo limite durante a criação da sessão

Soluções:

  • Aumentar o tempo limite da sessão: LivySessionTimeoutSeconds=120
  • Verificar a disponibilidade da capacidade do Fabric
  • Verificar se o workspace não atingiu os limites de sessão

Habilitar registro de log

Ao solucionar problemas, habilitar o log detalhado pode ajudá-lo a identificar a causa raiz dos problemas. Você pode habilitar o registro em log por meio da cadeia de conexão ou programaticamente.

Para habilitar o registro em log detalhado por meio de uma string de conexão:

LogLevel=Debug

Ou configure programaticamente:

using Microsoft.Extensions.Logging;

var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddConsole();
    builder.SetMinimumLevel(LogLevel.Debug);
});

// Logging is automatically integrated with the connection

Níveis de log:

  • Trace: mais detalhado, inclui todas as chamadas à API
  • Debug: informações detalhadas de depuração
  • Information: informações gerais (padrão)
  • Warning: somente avisos
  • Error: apenas erros