Microsoft ADO.NET Treiber für Microsoft Fabric Data Engineering (Vorschau)

Von Bedeutung

Dieses Feature befindet sich in der Vorschauphase.

ADO.NET ist eine weit verbreitete Datenzugriffstechnologie im .NET-Ökosystem, mit der Anwendungen eine Verbindung mit Daten aus Datenbanken und Big Data-Plattformen herstellen und damit arbeiten können.

Mit dem Microsoft ADO.NET Driver for Fabric Data Engineering können Sie Spark-Workloads in Microsoft Fabric mit der Zuverlässigkeit und Einfachheit von Standardmustern ADO.NET verbinden, abfragen und verwalten. Basierend auf den Livy-APIs von Microsoft Fabric bietet der Treiber sichere und flexible Spark SQL-Konnektivität zu Ihren .NET-Anwendungen mit vertrauten DbConnection, DbCommandund DbDataReader Abstraktionen.

Wichtigste Funktionen

  • ADO.NET Konform: Vollständige Implementierung von ADO.NET Abstraktionen (DbConnection, DbCommand, DbDataReader, DbParameter, ) DbProviderFactory
  • Microsoft Entra ID-Authentifizierung: Mehrere Authentifizierungsflüsse wie Azure CLI, interaktiver Browser, Clientanmeldeinformationen, zertifikatbasierte und Zugriffstokenauthentifizierung
  • Spark SQL Native Query Support: Direkte Ausführung von Spark SQL-Anweisungen mit parametrisierten Abfragen
  • Umfassende Unterstützung für Datentypen: Unterstützung für alle Spark SQL-Datentypen einschließlich komplexer Typen (ARRAY, MAP, STRUCT)
  • Verbindungspooling: Integrierte Verbindungspoolverwaltung für verbesserte Leistung
  • Sitzungswiederverwendung: Effiziente Spark-Sitzungsverwaltung zur Reduzierung der Startlatenz
  • Async Prefetch: Asynchrones Vorabrufen von Hintergrunddaten für verbesserte Leistung bei großen Ergebnis-Sets
  • Automatische Erneute Verbindung: Automatische Sitzungswiederherstellung nach Verbindungsfehlern

Hinweis

In Open-Source Apache Spark werden Datenbank und Schema synonym verwendet. Beispielsweise gibt die Ausführung SHOW SCHEMAS oder SHOW DATABASES in einem Fabric-Notizbuch dasselbe Ergebnis zurück – eine Liste aller Schemas im Lakehouse.

Voraussetzungen

Stellen Sie vor der Verwendung des Microsoft ADO.NET-Treibers für Microsoft Fabric Data Engineering folgendes sicher:

  • .NET Runtime: .NET 8.0 oder höher
  • Microsoft Fabric Access: Zugriff auf einen Microsoft Fabric-Arbeitsbereich mit Data Engineering-Funktionen
  • Azure Entra ID-Anmeldeinformationen: Geeignete Anmeldeinformationen für die Authentifizierung
  • Arbeitsbereichs- und Lakehouse-IDs: GUID-IDs für den Fabric-Arbeitsbereich und das Lakehouse
  • Azure CLI (optional): Erforderlich für die Azure CLI-Authentifizierungsmethode

Herunterladen, Einschließen, Verweisen und Überprüfen

NuGet-Paket herunterladen

Microsoft ADO.NET Driver für Microsoft Fabric Data Engineering Version 1.0.0 befindet sich in der öffentlichen Vorschau, die Sie über diese Download Center-Links herunterladen können.

Referenz nuGet-Paket in Ihrem Projekt

Fügen Sie das heruntergeladene NuGet-Paket in Ihr Projekt ein, und fügen Sie ihrer Projektdatei einen Verweis auf das Paket hinzu:

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

Überprüfen der Installation

Überprüfen Sie nach der Aufnahme und Referenz, ob das Paket in Ihrem Projekt verfügbar ist:

using Microsoft.Spark.Livy.AdoNet;

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

Schnellstartbeispiel

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 der Verbindungszeichenfolge

Standardformat

Der Microsoft ADO.NET-Treiber verwendet standardmäßiges ADO.NET Verbindungszeichenfolgenformat:

Parameter1=Value1;Parameter2=Value2;...

Erforderliche Parameter

Parameter Beschreibung Beispiel
Server Microsoft Fabric-API-Endpunkt https://api.fabric.microsoft.com/v1
SparkServerType Servertypbezeichner Fabric
FabricWorkspaceID Microsoft Fabric-Arbeitsbereichs-ID (GUID) <workspace-id>
FabricLakehouseID Microsoft Fabric Lakehouse-Bezeichner (GUID) <lakehouse-id>
AuthFlow Authentifizierungsmethode AzureCli, , BrowserBasedClientSecretCredential, ClientCertificateCredential, , AuthAccessTokenFileToken

Optionale Parameter

Verbindungseinstellungen

Parameter Typ Vorgabe Beschreibung
LivySessionTimeoutSeconds Integer 60 Zeit in Sekunden, bis die Sitzungserstellung gewartet wird
LivyStatementTimeoutSeconds Integer 600 Wartezeit in Sekunden bis zur Ausführung der Anweisung
SessionName String (automatisch) Benutzerdefinierter Name für die Spark-Sitzung
AutoReconnect Boolean false Aktivieren der automatischen Sitzungswiederherstellung

Verbindungspooleinstellungen

Parameter Typ Vorgabe Beschreibung
ConnectionPoolEnabled Boolean true Aktivieren von Verbindungspooling
MinPoolSize Integer 1 Mindestverbindungen im Pool
MaxPoolSize Integer 20 Maximale Anzahl an Verbindungen im Pool
ConnectionMaxIdleTimeMs Integer 1800000 Maximale Leerlaufzeit, bevor die Verbindung wiederverwendet wird (30 Min.)
MaxLifetimeMs Integer 3600000 Maximale Lebensdauer einer poolierten Verbindung (60 Min.)
ValidateConnections Boolean true Überprüfen von Verbindungen vor der Verwendung
ValidationTimeoutMs Integer 5000 Timeout für die Verbindungsüberprüfung

Logging-Einstellungen

Parameter Typ Vorgabe Beschreibung
LogLevel String Information Protokollebene: Trace, Debug, Information, , WarningError
LogFilePath String (kein) Pfad für die dateibasierte Protokollierung

Hinweis

Treiberübergreifende Aliase: Der Treiber akzeptiert neben systemeigenen ADO.NET-Namen auch JDBC- und ODBC-Property-Namen (z. B. WorkspaceId entspricht FabricWorkspaceID, LakehouseId entspricht FabricLakehouseID). Alle Eigenschaftsnamen sind groß- und kleinschreibungsunabhängig.

Exemplarische Verbindungszeichenfolgen

Grundlegende Verbindung (Azure CLI-Authentifizierung)

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

Mit Verbindungspoolingoptionen

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

Mit automatischer Wiederverbindung und Protokollierung

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

Authentifizierung

Der Microsoft ADO.NET Driver unterstützt mehrere Authentifizierungsmethoden über Microsoft Entra ID (früher Azure Active Directory). Die Authentifizierung wird mithilfe des AuthFlow Parameters in der Verbindungszeichenfolge konfiguriert.

Authentifizierungsmethoden

AuthFlow-Wert Beschreibung Am besten geeignet für
AzureCli Verwendet zwischengespeicherte Azure CLI-Anmeldeinformationen Entwickeln und Testen
BrowserBased Interaktive browserbasierte Authentifizierung Benutzerorientierte Anwendungen
ClientSecretCredential Dienstprinzipal mit Clientgeheimnis Automatisierte Dienste, Hintergrundaufträge
ClientCertificateCredential Dienstprinzipal mit Zertifikat Unternehmensanwendungen
AuthAccessToken Vorab erworbenes Bearerzugriffstoken Benutzerdefinierte Authentifizierungsszenarien

Azure CLI-Authentifizierung

Am besten geeignet für: Entwicklung und Tests

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 installiert: az --version
  • Angemeldet: az login

Interaktive Browserauthentifizierung

Am besten geeignet für: Benutzerorientierte Anwendungen

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

Verhalten:

  • Öffnet ein Browserfenster für die Benutzerauthentifizierung.
  • Anmeldeinformationen werden für nachfolgende Verbindungen zwischengespeichert.

Clientanmeldeinformationen (Dienstprinzipal)-Authentifizierung

Am besten geeignet für: Automatisierte Dienste und Hintergrundaufträge

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

Erforderliche Parameter:

  • AuthTenantID: Azure-Mandanten-ID
  • AuthClientID: Anwendungs-ID (Client-ID) von Microsoft Entra ID
  • AuthClientSecret: Geheimer Clientschlüssel von Microsoft Entra ID

Zertifikatbasierte Authentifizierung

Am besten geeignet für: Unternehmensanwendungen, die zertifikatbasierte Authentifizierung erfordern

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

Erforderliche Parameter:

  • AuthTenantID: Azure-Mandanten-ID
  • AuthClientID: Anwendungs-ID (Client-ID)
  • AuthCertificatePath: Pfad zur PFX/PKCS12-Zertifikatdatei
  • AuthCertificatePassword: Zertifikatkennwort

Zugriffstokenauthentifizierung

Am besten geeignet für: Benutzerdefinierte Authentifizierungsszenarien

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

Hinweis

Es wird dringend empfohlen, hartcodierende Anmeldeinformationen wie Kennwörter, Schlüssel, geheime Schlüssel, Token oder Zertifikate in Ihrem Code zu vermeiden. Verwenden Sie stattdessen Azure Key Vault, um diese Werte sicher zu speichern und zur Laufzeit abzurufen.

Verwendungsbeispiele

Grundlegende Verbindung und Abfrage

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

Parametrisierte Abfragen

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 für Einzelwerte

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

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

ExecuteNonQuery für DML-Vorgänge

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

Arbeiten mit großen Ergebnismengen

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

Schema-Ermittlung

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

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

Verwenden von 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...

Datentypzuordnung

Der Treiber ordnet Spark SQL-Datentypen .NET-Typen zu:

Spark SQL-Typ .NET-Typ DbType
BOOLEAN bool Boolean
TINYINT sbyte SByte
SMALLINT short Int16
INT int Int32
BIGINT long Int64
FLOAT float Ledig
DOUBLE double Double
DEZIMAL(p;s) decimal Decimal
STRING string String
VARCHAR(n) string String
CHAR(n) string String
BINÄR byte[] Binär
DATE DateTime Datum
TIMESTAMP DateTime DateTime
ARRAY<T> T[] oder string (JSON) Objekt
MAP<K,V> Dictionary<K,V> oder string (JSON) Objekt
STRUCT object oder string (JSON) Objekt

Arbeiten mit komplexen Typen

Komplexe Typen (ARRAY, MAP, STRUCT) werden standardmäßig als JSON-Zeichenfolgen zurückgegeben:

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

Problembehandlung

Dieser Abschnitt enthält Anleitungen zum Beheben häufiger Probleme, die bei verwendung des Microsoft ADO.NET-Treibers für Microsoft Fabric Data Engineering auftreten können.

Häufig auftretende Probleme

In den folgenden Abschnitten werden allgemeine Probleme und deren Lösungen beschrieben:

Verbindungsfehler

Problem: Verbindung mit Microsoft Fabric kann nicht hergestellt werden

Lösungen:

  1. Überprüfen Sie, ob FabricWorkspaceID und FabricLakehouseID korrekte GUIDs sind.
  2. Überprüfen sie die Azure CLI-Authentifizierung: az account show
  3. Stellen Sie sicher, dass Sie über entsprechende Fabric-Arbeitsbereichsberechtigungen verfügen.
  4. Überprüfen der Netzwerkkonnektivität mit api.fabric.microsoft.com

Authentifizierungsfehler

Problem: Die Authentifizierung schlägt mit Azure CLI fehl

Lösungen:

  • Ausführen az login zum Aktualisieren von Anmeldeinformationen
  • Überprüfen Sie, ob es sich um den richtigen Mandanten handelt: az account set --subscription <subscription-id>
  • Gültigkeit des Tokens überprüfen: az account get-access-token --resource https://api.fabric.microsoft.com

Abfrage-Timeouts

Problem: Abfragen, die bei großen Tabellen eine Zeitüberschreitung haben

Lösungen:

  • Zeitlimit der Anweisung erhöhen: LivyStatementTimeoutSeconds=300
  • Verwenden einer LIMIT Klausel zum Einschränken der Ergebnisgröße während der Entwicklung
  • Sicherstellen, dass Spark-Cluster über ausreichende Ressourcen verfügt

Timeout für die Sitzungserstellung

Problem: Verbindung läuft während der Sitzungserstellung ab

Lösungen:

  • Sitzungstimeout erhöhen: LivySessionTimeoutSeconds=120
  • Überprüfen der Verfügbarkeit der Fabric-Kapazität
  • Überprüfen, ob der Arbeitsbereich keine Sitzungsgrenzwerte erreicht hat

Aktivieren der Protokollierung

Beim Behandeln von Problemen kann das Aktivieren der detaillierten Protokollierung dabei helfen, die Ursache der Probleme zu identifizieren. Sie können die Protokollierung über die Verbindungszeichenfolge oder programmgesteuert aktivieren.

So aktivieren Sie die detaillierte Protokollierung über Verbindungszeichenfolge.

LogLevel=Debug

Oder programmgesteuert konfigurieren:

using Microsoft.Extensions.Logging;

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

// Logging is automatically integrated with the connection

Protokollebenen:

  • Trace: Am ausführlichsten, umfasst alle API-Aufrufe.
  • Debug: Detaillierte Debuginformationen
  • Information: Allgemeine Informationen (Standard)
  • Warning: Nur Warnungen
  • Error: Nur Fehler