Microsoft ADO.NET driver para Microsoft Fabric Data Engineering (versão preliminar)

Importante

Este recurso está em pré-visualização.

ADO.NET é uma tecnologia de acesso a dados amplamente adotada no ecossistema .NET que permite às aplicações conectar-se e trabalhar com dados provenientes de bases de dados e plataformas de big data.

O Microsoft ADO.NET Driver for Fabric Data Engineering permite-lhe ligar, consultar e gerir cargas de trabalho Spark no Microsoft Fabric com a fiabilidade e simplicidade dos padrões de ADO.NET padrão. Baseado nas APIs Livy do Microsoft Fabric, o driver oferece conectividade Spark SQL segura e flexível às suas aplicações .NET usando as abstrações familiares DbConnection, DbCommand e DbDataReader.

Principais características

  • ADO.NET Compatível: Implementação completa de abstrações ADO.NET (DbConnection, DbCommand, DbDataReader, DbParameter, DbProviderFactory)
  • Autenticação Microsoft Entra ID: Múltiplos fluxos de autenticação, incluindo Azure CLI, navegador interativo, credenciais de clientes, autenticação baseada em certificados e token de acesso
  • Suporte Nativo de Consultas SQL Spark: Execução direta de instruções SQL Spark com consultas parametrizadas
  • Suporte Abrangente de Tipos de Dados: Suporte para todos os tipos de dados SQL Spark, incluindo tipos complexos (ARRAY, MAP, STRUCT)
  • Pool de Conexões: Gestão integrada de pools de ligações para melhorar o desempenho
  • Reutilização de Sessões: Gestão eficiente das sessões Spark para reduzir a latência de arranque
  • 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 ligação

Observação

No Apache Spark de código aberto, base de dados e esquema são usados como sinónimos. Por exemplo, executar SHOW SCHEMAS ou SHOW DATABASES num Fabric Notebook devolve o mesmo resultado — uma lista de todos os esquemas no Lakehouse.

Pré-requisitos

Antes de usar o Microsoft ADO.NET Driver para Microsoft Fabric Data Engineering, certifique-se de que tem:

  • .NET Runtime: .NET 8.0 ou posterior
  • Acesso Microsoft Fabric: Acesso a um espaço de trabalho Microsoft Fabric com capacidades de Engenharia de Dados
  • Azure Entra ID Credentials: Credenciais apropriadas para autenticação
  • IDs de espaço de trabalho e casa do lago: identificadores GUID para o seu espaço de trabalho Fabric e casa do lago
  • Azure CLI (opcional): Necessário para o método de autenticação Azure CLI

Descarregar, incluir, referenciar e verificar

Descarregar o pacote NuGet

O Microsoft ADO.NET Driver for Microsoft Fabric Data Engineering versão 1.0.0 está em pré-visualização pública, que pode descarregar nestes links do centro de downloads.

Pacote NuGet de referência no seu projeto

Inclua o pacote NuGet descarregado no seu projeto e adicione uma referência do pacote ao ficheiro do projeto:

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

Verificar a instalação

Após inclusão e referência, verifique se o pacote está disponível no 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 Driver ADO.NET da Microsoft utiliza o formato padrão de cadeia de conexão ADO.NET.

Parameter1=Value1;Parameter2=Value2;...

Parâmetros necessários

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

Parâmetros opcionais

Definições de ligação

Parâmetro Tipo Predefinição Descrição
LivySessionTimeoutSeconds Número inteiro 60 Duração em segundos para aguardar a criação da sessão
LivyStatementTimeoutSeconds Número inteiro 600 Tempo em segundos para esperar pela execução de uma instrução
SessionName String (automático) Nome personalizado para a sessão Spark
AutoReconnect booleano false Ativar a recuperação automática de sessões

Definições do pool de conexão

Parâmetro Tipo Predefinição Descrição
ConnectionPoolEnabled booleano true Permitir o agrupamento de ligações
MinPoolSize Número inteiro 1 Ligações mínimas no pool
MaxPoolSize Número inteiro 20 Ligações máximas na piscina
ConnectionMaxIdleTimeMs Número inteiro 1800000 Tempo máximo de repouso antes de a ligação ser reciclada (30 min)
MaxLifetimeMs Número inteiro 3600000 Vida útil máxima de uma conexão agrupada (60 min)
ValidateConnections booleano true Validar as ligações antes da utilização
ValidationTimeoutMs Número inteiro 5000 Tempo limite para verificação da conexão

Configurações de registo

Parâmetro Tipo Predefinição Descrição
LogLevel String Information Nível de log: Trace, Debug, Information, Warning, Error
LogFilePath String (nenhum) Caminho para registo baseado em ficheiros

Observação

Aliases entre drivers: O driver aceita nomes de propriedades JDBC e ODBC além dos nomes nativos de ADO.NET (por exemplo, WorkspaceId mapeia para FabricWorkspaceID, LakehouseId mapeia para FabricLakehouseID). Todos os nomes de propriedades são insensíveis a maiúsculas e minúsculas.

Exemplo de cadeias de conexão

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

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 registo

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

Authentication

O Microsoft ADO.NET Driver suporta múltiplos métodos de autenticação através do Microsoft Entra ID (anteriormente Azure Active Directory). A autenticação é configurada usando o AuthFlow parâmetro na cadeia de ligação.

Métodos de autenticação

Valor AuthFlow Descrição Melhor Para
AzureCli Usa credenciais em cache do Azure CLI Desenvolvimento e testes
BrowserBased Autenticação interativa baseada em navegador Aplicações voltadas para o utilizador
ClientSecretCredential Principal de serviço com segredo de cliente Serviços automatizados, empregos secundários
ClientCertificateCredential Entidade de serviço com certificado Aplicações empresariais
AuthAccessToken Token de acesso pré-adquirido ao portador Cenários de autenticação personalizados

Autenticação da CLI do Azure

Melhor para: Desenvolvimento e testes

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();

Prerequisites:

  • Azure CLI instalado: az --version
  • Sessão iniciada: az login

Autenticação interativa do navegador

Melhor para: Aplicações voltadas para utilizadores

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 utilizador
  • As credenciais são armazenadas em cache para ligações subsequentes

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

Ideal para: Serviços automatizados e tarefas 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 exigidos:

  • AuthTenantID: Azure tenant ID
  • AuthClientID: ID da aplicação (cliente) a partir do ID Microsoft Entra
  • AuthClientSecret: Segredo do cliente do Microsoft Entra ID

Autenticação baseada em certificado

Ideal para: aplicações empresariais que requerem 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 exigidos:

  • AuthTenantID: Azure tenant ID
  • AuthClientID: ID da aplicação (cliente)
  • AuthCertificatePath: Caminho para o ficheiro de certificado PFX/PKCS12
  • AuthCertificatePassword: Palavra-passe 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

Recomendamos vivamente evitar credenciais de codificação rígida, como palavras-passe, chaves, segredos, tokens ou certificados no seu código. Em vez disso, use o Azure Key Vault para armazenar estes valores de forma segura e recuperá-los em tempo de execução.

Exemplos de utilização

Ligação básica e consulta

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 um único valor

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

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

ExecuteNonQuery para 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)");

Trabalhar 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 o 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 tipos de dados

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

Tipo SQL Spark Tipo .NET DbType
BOOLEANO 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
BINARY byte[] Binário
DATE DateTime Date
DATA E HORA DateTime DateTime
ARRAY<T> T[] ou string (JSON) Objeto
MAP<K,V> Dictionary<K,V> ou string (JSON) Objeto
STRUCT object ou string (JSON) Objeto

Trabalhar com tipos complexos

Tipos complexos (ARRAY, MAP, STRUCT) são devolvidos como cadeias JSON por defeito:

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);
}

Troubleshooting

Esta secção fornece orientações para resolver problemas comuns que possa encontrar ao utilizar o Microsoft ADO.NET Driver para Engenharia de Dados Microsoft Fabric.

Problemas comuns

As secções seguintes descrevem problemas comuns e as suas soluções:

Falhas de ligação

Problema: Não consegue ligar-se ao Microsoft Fabric

Soluções:

  1. Verifique se FabricWorkspaceID e FabricLakehouseID são GUIDs corretos
  2. Verificar a autenticação do Azure CLI: az account show
  3. Garante que tens as permissões adequadas para o espaço de trabalho do Fabric
  4. Verificar a conectividade de rede a api.fabric.microsoft.com

Erros de autenticação

Problema: A autenticação falha com o Azure CLI

Soluções:

  • Executar az login para atualizar as credenciais
  • Verifique o inquilino 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 a exceder o tempo limite em tabelas muito grandes

Soluções:

  • Aumentar o tempo de espera da declaração: LivyStatementTimeoutSeconds=300
  • Usar a cláusula LIMIT para restringir o tamanho do resultado durante o desenvolvimento.
  • Garantir que o cluster Spark dispõe de recursos adequados

Tempo limite de criação da sessão

Problema: A ligação expira durante a criação da sessão

Soluções:

  • Aumentar o tempo de pausa da sessão: LivySessionTimeoutSeconds=120
  • Verifique a disponibilidade de capacidade da rede Fabric
  • Verificar se o workspace ainda não atingiu os limites de sessão

Ativar log

Ao resolver problemas, ativar registos detalhados pode ajudar a identificar a causa raiz dos problemas. Podes ativar o registo através da string de ligação ou programaticamente.

Para permitir registos detalhados através da cadeia de ligação:

LogLevel=Debug

Ou configurar 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: O mais verboso, inclui todas as chamadas de API
  • Debug: Informação detalhada de depuração
  • Information: Informação geral (predefinição)
  • Warning: Apenas avisos
  • Error: Apenas erros