Pilote Microsoft ADO.NET pour Microsoft Fabric Data Engineering (préversion)

Important

Cette fonctionnalité est en version préliminaire.

ADO.NET est une technologie d’accès aux données largement adoptée dans l’écosystème .NET qui permet aux applications de se connecter et d’utiliser des données à partir de bases de données et de plateformes Big Data.

Microsoft ADO.NET Driver for Fabric Data Engineering vous permet de vous connecter, d’interroger et de gérer des charges de travail Spark dans Microsoft Fabric avec la fiabilité et la simplicité des modèles de ADO.NET standard. Basé sur les API Livy de Microsoft Fabric, le pilote fournit une connectivité Spark SQL sécurisée et flexible à vos applications .NET à l’aide d’abstractions familières DbConnection, DbCommand, et DbDataReader.

Fonctionnalités clés

  • Conforme à ADO.NET : implémentation complète des abstractions ADO.NET (DbConnection, DbCommand, DbDataReader, DbParameter, DbProviderFactory)
  • Authentification d’ID Microsoft Entra : plusieurs flux d’authentification, notamment Azure CLI, navigateur interactif, informations d’identification du client, authentification par certificat et jeton d’accès
  • Prise en charge des requêtes natives Spark SQL : exécution directe d’instructions Spark SQL avec des requêtes paramétrables
  • Prise en charge complète des types de données : prise en charge de tous les types de données Spark SQL, y compris les types complexes (ARRAY, MAP, STRUCT)
  • Regroupement de connexions : gestion intégrée du pool de connexions pour améliorer les performances
  • Réutilisation de session : Gestion efficace des sessions Spark pour réduire la latence de démarrage
  • Prérécupération asynchrone : chargement des données en arrière-plan pour améliorer les performances avec des jeux de résultats volumineux
  • Reconnexion automatique : récupération automatique de session après les échecs de connexion

Note

Dans Apache Spark open source, la base de données et le schéma sont utilisés comme synonymes. Par exemple, l’exécution SHOW SCHEMAS ou SHOW DATABASES dans un bloc-notes Fabric retourne le même résultat : une liste de tous les schémas dans Lakehouse.

Prerequisites

Avant d’utiliser Microsoft ADO.NET Driver pour Microsoft Fabric Data Engineering, vérifiez que vous disposez des points suivants :

  • Runtime .NET : .NET 8.0 ou version ultérieure
  • Accès à Microsoft Fabric : accès à un espace de travail Microsoft Fabric avec des fonctionnalités d’ingénierie des données
  • Informations d’identification d’ID Azure Entra : informations d’identification appropriées pour l’authentification
  • Identifiants d’espace de travail et de Lakehouse : identificateurs GUID pour votre espace de travail Fabric et votre Lakehouse.
  • Azure CLI (facultatif) : obligatoire pour la méthode d’authentification Azure CLI

Télécharger, inclure, référencer et vérifier

Télécharger le package NuGet

Microsoft ADO.NET Driver pour Microsoft Fabric Data Engineering version 1.0.0 est disponible en préversion publique que vous pouvez télécharger à partir de ces liens du centre de téléchargement.

Référencer le package NuGet dans votre projet

Incluez le package NuGet téléchargé dans votre projet et ajoutez une référence du package à votre fichier projet :

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

Vérifier l’installation

Après l’inclusion et la référence, vérifiez que le package est disponible dans votre projet :

using Microsoft.Spark.Livy.AdoNet;

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

Exemple de démarrage rapide

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

Format de la chaîne de connexion

Format de base

Microsoft ADO.NET Driver utilise le format de chaîne de connexion standard ADO.NET :

Parameter1=Value1;Parameter2=Value2;...

Paramètres obligatoires

Paramètre Description Exemple
Server Point de terminaison de l’API Microsoft Fabric https://api.fabric.microsoft.com/v1
SparkServerType Identificateur de type de serveur Fabric
FabricWorkspaceID Identificateur d’espace de travail Microsoft Fabric (GUID) <workspace-id>
FabricLakehouseID Identificateur Microsoft Fabric lakehouse (GUID) <lakehouse-id>
AuthFlow Méthode d’authentification AzureCli, , BrowserBased, ClientSecretCredentialClientCertificateCredential, , AuthAccessTokenFileToken

Paramètres facultatifs

Paramètres de connexion

Paramètre Type Par défaut Description
LivySessionTimeoutSeconds Nombre entier 60 Durée en secondes d’attente de la création de session
LivyStatementTimeoutSeconds Nombre entier 600 Durée en secondes d’attente de l’exécution de l’instruction
SessionName Chaîne (auto) Nom personnalisé de la session Spark
AutoReconnect Booléen false Activer la récupération automatique de session

Paramètres du pool de connexions

Paramètre Type Par défaut Description
ConnectionPoolEnabled Booléen true Activer le regroupement de connexions
MinPoolSize Nombre entier 1 Connexions minimales dans le pool
MaxPoolSize Nombre entier 20 Nombre maximal de connexions dans le pool
ConnectionMaxIdleTimeMs Nombre entier 1800000 Durée d’inactivité maximale avant le recyclage de la connexion (30 min)
MaxLifetimeMs Nombre entier 3600000 Durée de vie maximale d’une connexion mise en pool (60 min)
ValidateConnections Booléen true Valider les connexions avant l’utilisation
ValidationTimeoutMs Nombre entier 5000 Délai d’expiration de la validation de la connexion

Paramètres de journalisation

Paramètre Type Par défaut Description
LogLevel Chaîne Information Niveau de journalisation : Trace, Debug, Information, Warning, Error
LogFilePath Chaîne (aucun) Chemin d’accès à la journalisation basée sur des fichiers

Note

Alias inter-pilotes : Le pilote accepte les noms de propriétés JDBC et ODBC en plus des noms de ADO.NET natifs (par exemple, WorkspaceId mappe à FabricWorkspaceID, LakehouseId mappe à FabricLakehouseID). Tous les noms de propriétés sont insensibles à la casse.

Exemples de chaîne de connexion

Connexion de base (authentification Azure CLI)

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

Avec les options de regroupement de connexions

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

Avec la reconnexion automatique et la journalisation

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

Authentification

Microsoft ADO.NET Driver prend en charge plusieurs méthodes d’authentification via Microsoft Entra ID (anciennement Azure Active Directory). L’authentification est configurée à l’aide du AuthFlow paramètre dans la chaîne de connexion.

Méthodes d’authentification

Valeur AuthFlow Description Idéal pour
AzureCli Utilise les informations d'identification Azure CLI mises en cache Développement et test
BrowserBased Authentification interactive basée sur un navigateur Applications orientées utilisateur
ClientSecretCredential Principal du service avec secret client Services automatisés, travaux en arrière-plan
ClientCertificateCredential Principal de service avec certificat Applications d’entreprise
AuthAccessToken Jeton de porteur d'accès préacquis Scénarios d’authentification personnalisés

L'authentification de l'Azure CLI

Idéal pour : développement et test

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

Conditions préalables :

  • Azure CLI installé : az --version
  • Connecté : az login

Authentification interactive du navigateur

Idéal pour : applications accessibles par l’utilisateur

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

Comportement :

  • Ouvre une fenêtre de navigateur pour l’authentification utilisateur
  • Les informations d’identification sont mises en cache pour les connexions suivantes

Authentification des informations d’identification du client (principal de service)

Idéal pour : services automatisés et travaux en arrière-plan

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

Paramètres obligatoires :

  • AuthTenantID: ID de locataire Azure
  • AuthClientID: ID d’application (client) de Microsoft Entra ID
  • AuthClientSecret: Secret client de l'ID Microsoft Entra

Authentification basée sur un certificat

Idéal pour : les applications d’entreprise nécessitant une authentification basée sur des certificats

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

Paramètres obligatoires :

  • AuthTenantID: ID de locataire Azure
  • AuthClientID: ID d’application (client)
  • AuthCertificatePath: chemin d’accès au fichier de certificat PFX/PKCS12
  • AuthCertificatePassword: Mot de passe du certificat

Authentification par jeton d’accès

Idéal pour : scénarios d’authentification personnalisés

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

Note

Nous vous recommandons vivement d’éviter de coder en dur les informations d’identification telles que les mots de passe, les clés, les secrets, les jetons ou les certificats dans votre code. Utilisez plutôt Azure Key Vault pour stocker ces valeurs en toute sécurité et les récupérer au moment de l’exécution.

Exemples d’utilisation

Connexion et requête de base

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

Requêtes paramétrables

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 pour les valeurs uniques

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

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

ExecuteNonQuery pour les opérations 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)");

Utilisation de jeux de résultats volumineux

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

Découverte de schéma

// 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"]}");
}

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

Utilisation de 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...

Mappage de types de données

Le pilote mappe les types de données Spark SQL aux types .NET :

Type de Spark SQL type de .NET DbType
BOOLEAN bool Booléen
TINYINT sbyte SByte
SMALLINT short Int16
INT int Int32
BIGINT long Int64
FLOAT float Célibataire
DOUBLE double Double
DECIMAL(p,s) decimal Décimal
STRING string Chaîne
VARCHAR(n) string Chaîne
CHAR(n) string Chaîne
BINAIRE byte[] Binary
DATE DateTime Date
TIMESTAMP DateTime DateHeure
ARRAY<T> T[] ou string (JSON) Object
MAP<K,V> Dictionary<K,V> ou string (JSON) Object
STRUCT object ou string (JSON) Object

Utilisation de types complexes

Les types complexes (ARRAY, MAP, STRUCT) sont retournés sous forme de chaînes JSON par défaut :

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

Résolution des problèmes

Cette section fournit des conseils pour résoudre les problèmes courants que vous pouvez rencontrer lors de l’utilisation de Microsoft ADO.NET Driver pour Microsoft Fabric Data Engineering.

Problèmes courants

Les sections suivantes décrivent les problèmes courants et leurs solutions :

Échecs de connexion

Problème : Impossible de se connecter à Microsoft Fabric

Solutions :

  1. Vérifiez que FabricWorkspaceID et FabricLakehouseID sont des GUID corrects
  2. Vérifiez l’authentification Azure CLI : az account show
  3. Vérifiez que vous disposez des autorisations appropriées pour l’espace de travail Fabric
  4. Vérifier la connectivité réseau à api.fabric.microsoft.com

Erreurs d’authentification

Problème : l’authentification échoue avec Azure CLI

Solutions :

  • Exécuter az login pour actualiser les informations d’identification
  • Vérifiez le locataire correct : az account set --subscription <subscription-id>
  • Vérifiez la validité du jeton : az account get-access-token --resource https://api.fabric.microsoft.com

Délais d’expiration des requêtes

Problème : Les requêtes expirent sur des tables volumineuses

Solutions :

  • Augmentez le délai d’expiration de l’instruction : LivyStatementTimeoutSeconds=300
  • Utilisez la clause LIMIT pour restreindre la taille des résultats pendant le développement
  • Vérifier que le cluster Spark dispose de ressources adéquates

Délai d’expiration de la création de session

Problème : La connexion expire pendant la création de la session

Solutions :

  • Augmentez le délai d’expiration de session : LivySessionTimeoutSeconds=120
  • Vérifier la disponibilité de la capacité fabric
  • Vérifier que l’espace de travail n’a pas atteint les limites de session

Activation de la journalisation

Lors de la résolution des problèmes, l’activation de la journalisation détaillée peut vous aider à identifier la cause racine des problèmes. Vous pouvez activer la journalisation via la chaîne de connexion ou par programmation.

Pour activer la journalisation détaillée via la chaîne de connexion :

LogLevel=Debug

Ou configurez par programme :

using Microsoft.Extensions.Logging;

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

// Logging is automatically integrated with the connection

Niveaux de journalisation :

  • Trace: La plus détaillée, inclut tous les appels d'API
  • Debug: Informations de débogage détaillées
  • Information: Informations générales (par défaut)
  • Warning: Avertissements uniquement
  • Error: erreurs uniquement