GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

azure-resource-manager-sql-dotnet

Azure Resource Manager SDK for Azure SQL in .NET. Use for MANAGEMENT PLANE operations: creating/managing SQL servers, databases, elastic pools, firewall rules, and failover groups via Azure Resource Manager. NOT for data plane operations (executing queries) - use Microsoft.Data.S

Ciza · 0 points · 16 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_plugins_azure-sdk-dotnet_skills_azure-resource-manager-sql-dotnet-e58528d.zip · 9 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-dotnet/skills/azure-resource-manager-sql-dotnet
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Azure.ResourceManager.Sql (.NET)

Management plane SDK for provisioning and managing Azure SQL resources via Azure Resource Manager.

⚠️ Management vs Data Plane

  • This SDK (Azure.ResourceManager.Sql): Create servers, databases, elastic pools, configure firewall rules, manage failover groups
  • Data Plane SDK (Microsoft.Data.SqlClient): Execute queries, stored procedures, manage connections

Installation

dotnet add package Azure.ResourceManager.Sql
dotnet add package Azure.Identity

Current Versions: Stable v1.3.0, Preview v1.4.0-beta.3

Environment Variables

AZURE_SUBSCRIPTION_ID=<your-subscription-id>  # Required: Azure subscription ID
AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production
AZURE_TENANT_ID=<tenant-id>  # For service principal auth (optional)
AZURE_CLIENT_ID=<client-id>  # For service principal auth (optional)
AZURE_CLIENT_SECRET=<client-secret>  # For service principal auth (optional)

Authentication

using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Sql;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
var credential = new DefaultAzureCredential(
    DefaultAzureCredential.DefaultEnvironmentVariableName
);
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/dotnet/api/overview/azure/identity-readme?view=azure-dotnet#credential-classes
// var credential = new ManagedIdentityCredential();
var armClient = new ArmClient(credential);

// Get subscription
var subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID");
var subscription = armClient.GetSubscriptionResource(
    new ResourceIdentifier($"/subscriptions/{subscriptionId}"));

Resource Hierarchy

ArmClient
└── SubscriptionResource
    └── ResourceGroupResource
        └── SqlServerResource
            ├── SqlDatabaseResource
            ├── ElasticPoolResource
            │   └── ElasticPoolDatabaseResource
            ├── SqlFirewallRuleResource
            ├── FailoverGroupResource
            ├── ServerBlobAuditingPolicyResource
            ├── EncryptionProtectorResource
            └── VirtualNetworkRuleResource

Core Workflow

1. Create SQL Server

using Azure.ResourceManager.Sql;
using Azure.ResourceManager.Sql.Models;

// Get resource group
var resourceGroup = await subscription
    .GetResourceGroupAsync("my-resource-group");

// Define server
var serverData = new SqlServerData(AzureLocation.EastUS)
{
    AdministratorLogin = "sqladmin",
    AdministratorLoginPassword = "YourSecurePassword123!",
    Version = "12.0",
    MinimalTlsVersion = SqlMinimalTlsVersion.Tls1_2,
    PublicNetworkAccess = ServerNetworkAccessFlag.Enabled
};

// Create server (long-running operation)
var serverCollection = resourceGroup.Value.GetSqlServers();
var operation = await serverCollection.CreateOrUpdateAsync(
    WaitUntil.Completed,
    "my-sql-server",
    serverData);

SqlServerResource server = operation.Value;

2. Create SQL Database

var databaseData = new SqlDatabaseData(AzureLocation.EastUS)
{
    Sku = new SqlSku("S0") { Tier = "Standard" },
    MaxSizeBytes = 2L * 1024 * 1024 * 1024, // 2 GB
    Collation = "SQL_Latin1_General_CP1_CI_AS",
    RequestedBackupStorageRedundancy = SqlBackupStorageRedundancy.Local
};

var databaseCollection = server.GetSqlDatabases();
var dbOperation = await databaseCollection.CreateOrUpdateAsync(
    WaitUntil.Completed,
    "my-database",
    databaseData);

SqlDatabaseResource database = dbOperation.Value;

3. Create Elastic Pool

var poolData = new ElasticPoolData(AzureLocation.EastUS)
{
    Sku = new SqlSku("StandardPool")
    {
        Tier = "Standard",
        Capacity = 100 // 100 eDTUs
    },
    PerDatabaseSettings = new ElasticPoolPerDatabaseSettings
    {
        MinCapacity = 0,
        MaxCapacity = 100
    }
};

var poolCollection = server.GetElasticPools();
var poolOperation = await poolCollection.CreateOrUpdateAsync(
    WaitUntil.Completed,
    "my-elastic-pool",
    poolData);

ElasticPoolResource pool = poolOperation.Value;

4. Add Database to Elastic Pool

var databaseData = new SqlDatabaseData(AzureLocation.EastUS)
{
    ElasticPoolId = pool.Id
};

await databaseCollection.CreateOrUpdateAsync(
    WaitUntil.Completed,
    "pooled-database",
    databaseData);

5. Configure Firewall Rules

// Allow Azure services
var azureServicesRule = new SqlFirewallRuleData
{
    StartIPAddress = "0.0.0.0",
    EndIPAddress = "0.0.0.0"
};

var firewallCollection = server.GetSqlFirewallRules();
await firewallCollection.CreateOrUpdateAsync(
    WaitUntil.Completed,
    "AllowAzureServices",
    azureServicesRule);

// Allow specific IP range
var clientRule = new SqlFirewallRuleData
{
    StartIPAddress = "203.0.113.0",
    EndIPAddress = "203.0.113.255"
};

await firewallCollection.CreateOrUpdateAsync(
    WaitUntil.Completed,
    "AllowClientIPs",
    clientRule);

6. List Resources

// List all servers in subscription
await foreach (var srv in subscription.GetSqlServersAsync())
{
    Console.WriteLine($"Server: {srv.Data.Name} in {srv.Data.Location}");
}

// List databases in a server
await foreach (var db in server.GetSqlDatabases())
{
    Console.WriteLine($"Database: {db.Data.Name}, SKU: {db.Data.Sku?.Name}");
}

// List elastic pools
await foreach (var ep in server.GetElasticPools())
{
    Console.WriteLine($"Pool: {ep.Data.Name}, DTU: {ep.Data.Sku?.Capacity}");
}

7. Get Connection String

// Build connection string (server FQDN is predictable)
var serverFqdn = $"{server.Data.Name}.database.windows.net";
var connectionString = $"Server=tcp:{serverFqdn},1433;" +
    $"Initial Catalog={database.Data.Name};" +
    "Persist Security Info=False;" +
    $"User ID={server.Data.AdministratorLogin};" +
    "Password=<your-password>;" +
    "MultipleActiveResultSets=False;" +
    "Encrypt=True;" +
    "TrustServerCertificate=False;" +
    "Connection Timeout=30;";

Key Types Reference

Type Purpose
ArmClient Entry point for all ARM operations
SqlServerResource Represents an Azure SQL server
SqlServerCollection Collection for server CRUD
SqlDatabaseResource Represents a SQL database
SqlDatabaseCollection Collection for database CRUD
ElasticPoolResource Represents an elastic pool
ElasticPoolCollection Collection for elastic pool CRUD
SqlFirewallRuleResource Represents a firewall rule
SqlFirewallRuleCollection Collection for firewall rule CRUD
SqlServerData Server creation/update payload
SqlDatabaseData Database creation/update payload
ElasticPoolData Elastic pool creation/update payload
SqlFirewallRuleData Firewall rule creation/update payload
SqlSku SKU configuration (tier, capacity)

Common SKUs

Database SKUs

SKU Name Tier Description
Basic Basic 5 DTUs, 2 GB max
S0-S12 Standard 10-3000 DTUs
P1-P15 Premium 125-4000 DTUs
GP_Gen5_2 GeneralPurpose vCore-based, 2 vCores
BC_Gen5_2 BusinessCritical vCore-based, 2 vCores
HS_Gen5_2 Hyperscale vCore-based, 2 vCores

Elastic Pool SKUs

SKU Name Tier Description
BasicPool Basic 50-1600 eDTUs
StandardPool Standard 50-3000 eDTUs
PremiumPool Premium 125-4000 eDTUs
GP_Gen5_2 GeneralPurpose vCore-based
BC_Gen5_2 BusinessCritical vCore-based

Best Practices

  1. Use WaitUntil.Completed for operations that must finish before proceeding
  2. Use WaitUntil.Started when you want to poll manually or run operations in parallel
  3. Always use DefaultAzureCredential — never hardcode passwords in production
  4. Handle RequestFailedException for ARM API errors
  5. Use CreateOrUpdateAsync for idempotent operations
  6. Navigate hierarchy via Get* methods (e.g., server.GetSqlDatabases())
  7. Use elastic pools for cost optimization when managing multiple databases
  8. Configure firewall rules before attempting connections

Error Handling

using Azure;

try
{
    var operation = await serverCollection.CreateOrUpdateAsync(
        WaitUntil.Completed, serverName, serverData);
}
catch (RequestFailedException ex) when (ex.Status == 409)
{
    Console.WriteLine("Server already exists");
}
catch (RequestFailedException ex) when (ex.Status == 400)
{
    Console.WriteLine($"Invalid request: {ex.Message}");
}
catch (RequestFailedException ex)
{
    Console.WriteLine($"ARM Error: {ex.Status} - {ex.ErrorCode}: {ex.Message}");
}

Reference Files

File When to Read
references/server-management.md Server CRUD, admin credentials, Azure AD auth, networking
references/database-operations.md Database CRUD, scaling, backup, restore, copy
references/elastic-pools.md Pool management, adding/removing databases, scaling

Related SDKs

SDK Purpose Install
Microsoft.Data.SqlClient Data plane (execute queries, stored procedures) dotnet add package Microsoft.Data.SqlClient
Azure.ResourceManager.Sql Management plane (this SDK) dotnet add package Azure.ResourceManager.Sql
Microsoft.EntityFrameworkCore.SqlServer ORM for SQL Server dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Files (skills)
  • references
    • database-operations.md 6.8 KB
      # Database Operations
      
      Advanced database operations for Azure SQL.
      
      ## Create Database with vCore SKU
      
      ```csharp
      using Azure.ResourceManager.Sql;
      using Azure.ResourceManager.Sql.Models;
      
      var databaseData = new SqlDatabaseData(AzureLocation.EastUS)
      {
          Sku = new SqlSku("GP_Gen5_2")
          {
              Tier = "GeneralPurpose",
              Family = "Gen5",
              Capacity = 2 // vCores
          },
          MaxSizeBytes = 32L * 1024 * 1024 * 1024, // 32 GB
          ZoneRedundant = false,
          ReadScale = SqlDatabaseReadScale.Disabled,
          RequestedBackupStorageRedundancy = SqlBackupStorageRedundancy.Geo
      };
      
      var operation = await databaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-vcore-database",
          databaseData);
      ```
      
      ## Create Serverless Database
      
      ```csharp
      var databaseData = new SqlDatabaseData(AzureLocation.EastUS)
      {
          Sku = new SqlSku("GP_S_Gen5_2")
          {
              Tier = "GeneralPurpose",
              Family = "Gen5",
              Capacity = 2 // Max vCores
          },
          AutoPauseDelay = 60, // Minutes of inactivity before auto-pause
          MinCapacity = 0.5,   // Minimum vCores (can be fractional)
          MaxSizeBytes = 32L * 1024 * 1024 * 1024
      };
      
      await databaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-serverless-db",
          databaseData);
      ```
      
      ## Scale Database
      
      ```csharp
      // Get existing database
      var database = await databaseCollection.GetAsync("my-database");
      
      // Update SKU
      var updateData = new SqlDatabaseData(database.Value.Data.Location)
      {
          Sku = new SqlSku("S3") { Tier = "Standard" }
      };
      
      await databaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-database",
          updateData);
      ```
      
      ## Copy Database
      
      ```csharp
      var copyData = new SqlDatabaseData(AzureLocation.EastUS)
      {
          CreateMode = SqlDatabaseCreateMode.Copy,
          SourceDatabaseId = sourceDatabase.Id,
          Sku = new SqlSku("S0") { Tier = "Standard" }
      };
      
      await targetDatabaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "database-copy",
          copyData);
      ```
      
      ## Restore Database from Point-in-Time
      
      ```csharp
      var restoreData = new SqlDatabaseData(AzureLocation.EastUS)
      {
          CreateMode = SqlDatabaseCreateMode.PointInTimeRestore,
          SourceDatabaseId = sourceDatabase.Id,
          RestorePointInTime = DateTimeOffset.UtcNow.AddHours(-2), // 2 hours ago
          Sku = new SqlSku("S0") { Tier = "Standard" }
      };
      
      await databaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "restored-database",
          restoreData);
      ```
      
      ## Restore Deleted Database
      
      ```csharp
      // List deleted databases
      var deletedDatabases = server.GetRestorableDroppedDatabases();
      
      await foreach (var deleted in deletedDatabases)
      {
          Console.WriteLine($"Deleted: {deleted.Data.DatabaseName} at {deleted.Data.DeletionOn}");
          
          // Restore the deleted database
          var restoreData = new SqlDatabaseData(AzureLocation.EastUS)
          {
              CreateMode = SqlDatabaseCreateMode.Restore,
              RestorableDroppedDatabaseId = deleted.Id,
              Sku = new SqlSku("S0") { Tier = "Standard" }
          };
          
          await databaseCollection.CreateOrUpdateAsync(
              WaitUntil.Completed,
              "restored-deleted-db",
              restoreData);
          
          break; // Restore first one
      }
      ```
      
      ## Geo-Restore Database
      
      ```csharp
      // List recoverable databases (geo-replicated backups)
      var recoverableDatabases = server.GetRecoverableDatabases();
      
      await foreach (var recoverable in recoverableDatabases)
      {
          var restoreData = new SqlDatabaseData(AzureLocation.WestUS) // Different region
          {
              CreateMode = SqlDatabaseCreateMode.Recovery,
              RecoverableDatabaseId = recoverable.Id,
              Sku = new SqlSku("S0") { Tier = "Standard" }
          };
          
          await targetDatabaseCollection.CreateOrUpdateAsync(
              WaitUntil.Completed,
              "geo-restored-db",
              restoreData);
          
          break;
      }
      ```
      
      ## Configure Long-Term Retention
      
      ```csharp
      var ltrPolicy = new LongTermRetentionPolicyData
      {
          WeeklyRetention = "P4W",  // 4 weeks
          MonthlyRetention = "P12M", // 12 months
          YearlyRetention = "P5Y",   // 5 years
          WeekOfYear = 1 // First week for yearly backup
      };
      
      var ltrPolicyResource = database.GetLongTermRetentionPolicy();
      await ltrPolicyResource.CreateOrUpdateAsync(
          WaitUntil.Completed,
          ltrPolicy);
      ```
      
      ## Configure Short-Term Retention
      
      ```csharp
      var strPolicy = new ShortTermRetentionPolicyData
      {
          RetentionDays = 14, // 7-35 days
          DiffBackupIntervalInHours = 12 // 12 or 24 hours
      };
      
      var strPolicyResource = database.GetShortTermRetentionPolicy();
      await strPolicyResource.CreateOrUpdateAsync(
          WaitUntil.Completed,
          strPolicy);
      ```
      
      ## Export Database to Bacpac
      
      ```csharp
      var exportRequest = new DatabaseExportDefinition
      {
          StorageKeyType = StorageKeyType.StorageAccessKey,
          StorageKey = "<storage-account-key>",
          StorageUri = new Uri("https://mystorageaccount.blob.core.windows.net/backups/mydb.bacpac"),
          AdministratorLogin = "sqladmin",
          AdministratorLoginPassword = "YourPassword123!"
      };
      
      var exportOperation = await database.ExportAsync(WaitUntil.Completed, exportRequest);
      ```
      
      ## Import Database from Bacpac
      
      ```csharp
      var importRequest = new ImportExistingDatabaseDefinition
      {
          StorageKeyType = StorageKeyType.StorageAccessKey,
          StorageKey = "<storage-account-key>",
          StorageUri = new Uri("https://mystorageaccount.blob.core.windows.net/backups/mydb.bacpac"),
          AdministratorLogin = "sqladmin",
          AdministratorLoginPassword = "YourPassword123!"
      };
      
      // Import into existing database
      var importOperation = await database.ImportAsync(WaitUntil.Completed, importRequest);
      ```
      
      ## Rename Database
      
      ```csharp
      var renameRequest = new ResourceMoveDefinition(
          new ResourceIdentifier($"{server.Id}/databases/new-database-name"));
      
      await database.RenameAsync(renameRequest);
      ```
      
      ## Delete Database
      
      ```csharp
      var database = await databaseCollection.GetAsync("my-database");
      await database.Value.DeleteAsync(WaitUntil.Completed);
      ```
      
      ## Transparent Data Encryption
      
      ```csharp
      // TDE is enabled by default for new databases
      // To check or modify:
      var tdeResource = database.GetSqlDatabaseTransparentDataEncryption();
      var tde = await tdeResource.GetAsync();
      
      Console.WriteLine($"TDE State: {tde.Value.Data.State}");
      
      // Disable TDE (not recommended)
      var tdeData = new SqlDatabaseTransparentDataEncryptionData
      {
          State = TransparentDataEncryptionState.Disabled
      };
      await tdeResource.CreateOrUpdateAsync(WaitUntil.Completed, tdeData);
      ```
      
      ## Database Threat Detection
      
      ```csharp
      var threatDetectionData = new SqlDatabaseSecurityAlertPolicyData
      {
          State = SecurityAlertsPolicyState.Enabled,
          DisabledAlerts = { }, // Empty = all alerts enabled
          EmailAddresses = { "security@contoso.com" },
          EmailAccountAdmins = true,
          RetentionDays = 30,
          StorageEndpoint = "https://mystorageaccount.blob.core.windows.net",
          StorageAccountAccessKey = "<storage-key>"
      };
      
      var securityPolicy = database.GetSqlDatabaseSecurityAlertPolicy();
      await securityPolicy.CreateOrUpdateAsync(WaitUntil.Completed, threatDetectionData);
      ```
      
    • elastic-pools.md 5.8 KB
      # Elastic Pools
      
      Elastic pool management for Azure SQL.
      
      ## Create DTU-Based Elastic Pool
      
      ```csharp
      using Azure.ResourceManager.Sql;
      using Azure.ResourceManager.Sql.Models;
      
      var poolData = new ElasticPoolData(AzureLocation.EastUS)
      {
          Sku = new SqlSku("StandardPool")
          {
              Tier = "Standard",
              Capacity = 100 // 100 eDTUs
          },
          PerDatabaseSettings = new ElasticPoolPerDatabaseSettings
          {
              MinCapacity = 0,   // Min eDTUs per database
              MaxCapacity = 100  // Max eDTUs per database
          }
      };
      
      var poolCollection = server.GetElasticPools();
      var operation = await poolCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-standard-pool",
          poolData);
      
      ElasticPoolResource pool = operation.Value;
      ```
      
      ## Create vCore-Based Elastic Pool
      
      ```csharp
      var poolData = new ElasticPoolData(AzureLocation.EastUS)
      {
          Sku = new SqlSku("GP_Gen5_2")
          {
              Tier = "GeneralPurpose",
              Family = "Gen5",
              Capacity = 2 // vCores
          },
          PerDatabaseSettings = new ElasticPoolPerDatabaseSettings
          {
              MinCapacity = 0,
              MaxCapacity = 2
          },
          ZoneRedundant = false,
          LicenseType = DatabaseLicenseType.LicenseIncluded // or BasePrice for Azure Hybrid Benefit
      };
      
      await poolCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-vcore-pool",
          poolData);
      ```
      
      ## Create Premium Elastic Pool with Zone Redundancy
      
      ```csharp
      var poolData = new ElasticPoolData(AzureLocation.EastUS)
      {
          Sku = new SqlSku("PremiumPool")
          {
              Tier = "Premium",
              Capacity = 125 // 125 eDTUs
          },
          PerDatabaseSettings = new ElasticPoolPerDatabaseSettings
          {
              MinCapacity = 0,
              MaxCapacity = 125
          },
          ZoneRedundant = true
      };
      
      await poolCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-premium-pool",
          poolData);
      ```
      
      ## Add Database to Elastic Pool
      
      ```csharp
      // Create new database in pool
      var databaseData = new SqlDatabaseData(AzureLocation.EastUS)
      {
          ElasticPoolId = pool.Id
      };
      
      await databaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "pooled-database",
          databaseData);
      ```
      
      ## Move Existing Database to Elastic Pool
      
      ```csharp
      // Get existing database
      var database = await databaseCollection.GetAsync("standalone-database");
      
      // Update to use elastic pool
      var updateData = new SqlDatabaseData(database.Value.Data.Location)
      {
          ElasticPoolId = pool.Id
      };
      
      await databaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "standalone-database",
          updateData);
      ```
      
      ## Remove Database from Elastic Pool
      
      ```csharp
      // Move database out of pool by assigning a standalone SKU
      var updateData = new SqlDatabaseData(database.Value.Data.Location)
      {
          Sku = new SqlSku("S0") { Tier = "Standard" },
          ElasticPoolId = null
      };
      
      await databaseCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "pooled-database",
          updateData);
      ```
      
      ## Scale Elastic Pool
      
      ```csharp
      var pool = await poolCollection.GetAsync("my-elastic-pool");
      
      var updateData = new ElasticPoolData(pool.Value.Data.Location)
      {
          Sku = new SqlSku("StandardPool")
          {
              Tier = "Standard",
              Capacity = 200 // Scale up to 200 eDTUs
          },
          PerDatabaseSettings = new ElasticPoolPerDatabaseSettings
          {
              MinCapacity = 10,
              MaxCapacity = 100
          }
      };
      
      await poolCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-elastic-pool",
          updateData);
      ```
      
      ## List Databases in Elastic Pool
      
      ```csharp
      var pool = await poolCollection.GetAsync("my-elastic-pool");
      
      // Get databases in this pool
      var poolDatabases = pool.Value.GetElasticPoolDatabases();
      
      await foreach (var db in poolDatabases)
      {
          Console.WriteLine($"Database: {db.Data.Name}");
          Console.WriteLine($"  Current SKU: {db.Data.CurrentSku?.Name}");
          Console.WriteLine($"  Max Size: {db.Data.MaxSizeBytes / (1024 * 1024 * 1024)} GB");
      }
      ```
      
      ## Monitor Elastic Pool Metrics
      
      ```csharp
      // Get pool resource utilization
      var pool = await poolCollection.GetAsync("my-elastic-pool");
      
      // Pool metrics are available via Azure Monitor
      // Use Azure.ResourceManager.Monitor for detailed metrics
      
      Console.WriteLine($"Pool: {pool.Value.Data.Name}");
      Console.WriteLine($"State: {pool.Value.Data.State}");
      Console.WriteLine($"Max Size: {pool.Value.Data.MaxSizeBytes / (1024 * 1024 * 1024)} GB");
      Console.WriteLine($"DTU Capacity: {pool.Value.Data.Sku?.Capacity}");
      ```
      
      ## Delete Elastic Pool
      
      ```csharp
      // First, move all databases out of the pool or delete them
      var pool = await poolCollection.GetAsync("my-elastic-pool");
      
      // Check for databases
      var poolDatabases = pool.Value.GetElasticPoolDatabases();
      await foreach (var db in poolDatabases)
      {
          // Either delete or move to standalone
          await db.DeleteAsync(WaitUntil.Completed);
      }
      
      // Now delete the pool
      await pool.Value.DeleteAsync(WaitUntil.Completed);
      ```
      
      ## Elastic Pool SKU Reference
      
      ### DTU-Based Pools
      
      | SKU Name | Tier | eDTU Range | Max DBs |
      |----------|------|------------|---------|
      | `BasicPool` | Basic | 50-1600 | 500 |
      | `StandardPool` | Standard | 50-3000 | 500 |
      | `PremiumPool` | Premium | 125-4000 | 100 |
      
      ### vCore-Based Pools
      
      | SKU Pattern | Tier | vCore Range |
      |-------------|------|-------------|
      | `GP_Gen5_{n}` | GeneralPurpose | 2-80 |
      | `GP_Fsv2_{n}` | GeneralPurpose | 8-72 |
      | `GP_DC_{n}` | GeneralPurpose | 2-8 |
      | `BC_Gen5_{n}` | BusinessCritical | 2-80 |
      | `BC_DC_{n}` | BusinessCritical | 2-8 |
      
      ## Best Practices
      
      1. **Right-size pools**: Start with estimated total DTU/vCore needs, monitor, and adjust
      2. **Set per-database limits**: Prevent a single database from consuming all resources
      3. **Use zone redundancy** for production Premium/BusinessCritical pools
      4. **Monitor utilization**: Scale up when consistently above 80% utilization
      5. **Consider Hyperscale**: For databases > 4TB or needing rapid scale
      6. **Use Azure Hybrid Benefit**: Set `LicenseType = BasePrice` if you have SQL Server licenses
      
    • server-management.md 5.2 KB
      # Server Management
      
      Advanced server operations for Azure SQL.
      
      ## Create Server with Azure AD Authentication
      
      ```csharp
      using Azure.ResourceManager.Sql;
      using Azure.ResourceManager.Sql.Models;
      
      var serverData = new SqlServerData(AzureLocation.EastUS)
      {
          // SQL authentication (optional, can be disabled)
          AdministratorLogin = "sqladmin",
          AdministratorLoginPassword = "YourSecurePassword123!",
          
          // Azure AD authentication
          Administrators = new ServerExternalAdministrator
          {
              AdministratorType = SqlAdministratorType.ActiveDirectory,
              Login = "admin@contoso.com",
              Sid = Guid.Parse("<azure-ad-user-object-id>"),
              TenantId = Guid.Parse("<azure-ad-tenant-id>"),
              AzureADOnlyAuthentication = false // Set true to disable SQL auth
          },
          
          Version = "12.0",
          MinimalTlsVersion = SqlMinimalTlsVersion.Tls1_2
      };
      
      var operation = await serverCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-sql-server",
          serverData);
      ```
      
      ## Update Server Administrator Password
      
      ```csharp
      // Get existing server
      var server = await serverCollection.GetAsync("my-sql-server");
      
      // Update password (requires full server data)
      var updateData = server.Value.Data;
      // Note: Password cannot be read, only set
      // You need to create new SqlServerData with the new password
      
      var newServerData = new SqlServerData(server.Value.Data.Location)
      {
          AdministratorLogin = server.Value.Data.AdministratorLogin,
          AdministratorLoginPassword = "NewSecurePassword456!"
      };
      
      await serverCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "my-sql-server",
          newServerData);
      ```
      
      ## Configure Public Network Access
      
      ```csharp
      var serverData = new SqlServerData(AzureLocation.EastUS)
      {
          AdministratorLogin = "sqladmin",
          AdministratorLoginPassword = "YourSecurePassword123!",
          
          // Disable public access (use private endpoints only)
          PublicNetworkAccess = ServerNetworkAccessFlag.Disabled,
          
          // Or enable with restrictions
          // PublicNetworkAccess = ServerNetworkAccessFlag.Enabled,
          // RestrictOutboundNetworkAccess = ServerNetworkAccessFlag.Enabled
      };
      ```
      
      ## Get Server by Resource ID
      
      ```csharp
      var resourceId = SqlServerResource.CreateResourceIdentifier(
          subscriptionId,
          "my-resource-group",
          "my-sql-server");
      
      var server = armClient.GetSqlServerResource(resourceId);
      var serverData = await server.GetAsync();
      ```
      
      ## Delete Server
      
      ```csharp
      var server = await serverCollection.GetAsync("my-sql-server");
      await server.Value.DeleteAsync(WaitUntil.Completed);
      ```
      
      ## Check Server Name Availability
      
      ```csharp
      var checkRequest = new SqlNameAvailabilityContent
      {
          Name = "proposed-server-name",
          ResourceType = "Microsoft.Sql/servers"
      };
      
      var result = await subscription.CheckSqlNameAvailabilityAsync(checkRequest);
      
      if (result.Value.IsAvailable == true)
      {
          Console.WriteLine("Name is available");
      }
      else
      {
          Console.WriteLine($"Name unavailable: {result.Value.Reason}");
      }
      ```
      
      ## Virtual Network Rules
      
      ```csharp
      // Allow access from a specific subnet
      var vnetRuleData = new SqlServerVirtualNetworkRuleData
      {
          VirtualNetworkSubnetId = new ResourceIdentifier(
              "/subscriptions/{sub}/resourceGroups/{rg}/providers/" +
              "Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet}"),
          IgnoreMissingVnetServiceEndpoint = false
      };
      
      var vnetRuleCollection = server.GetSqlServerVirtualNetworkRules();
      await vnetRuleCollection.CreateOrUpdateAsync(
          WaitUntil.Completed,
          "allow-app-subnet",
          vnetRuleData);
      ```
      
      ## Private Endpoints
      
      ```csharp
      // Private endpoints are created via Microsoft.Network, not SQL SDK
      // The SQL server just needs PublicNetworkAccess = Disabled
      
      // After creating private endpoint, approve the connection:
      var privateEndpointConnections = server.GetSqlServerPrivateEndpointConnections();
      
      await foreach (var connection in privateEndpointConnections)
      {
          if (connection.Data.PrivateLinkServiceConnectionState.Status == "Pending")
          {
              // Approve the connection
              var approvalData = connection.Data;
              approvalData.PrivateLinkServiceConnectionState.Status = "Approved";
              approvalData.PrivateLinkServiceConnectionState.Description = "Approved by admin";
              
              await privateEndpointConnections.CreateOrUpdateAsync(
                  WaitUntil.Completed,
                  connection.Data.Name,
                  approvalData);
          }
      }
      ```
      
      ## Server Auditing
      
      ```csharp
      var auditingData = new SqlServerBlobAuditingPolicyData
      {
          State = BlobAuditingPolicyState.Enabled,
          StorageEndpoint = "https://mystorageaccount.blob.core.windows.net",
          StorageAccountAccessKey = "<storage-account-key>",
          RetentionDays = 90,
          IsStorageSecondaryKeyInUse = false,
          IsAzureMonitorTargetEnabled = true
      };
      
      var auditingPolicy = server.GetSqlServerBlobAuditingPolicy();
      await auditingPolicy.CreateOrUpdateAsync(WaitUntil.Completed, auditingData);
      ```
      
      ## Transparent Data Encryption (Server-Level Key)
      
      ```csharp
      // Configure customer-managed key for TDE
      var protectorData = new EncryptionProtectorData
      {
          ServerKeyType = SqlServerKeyType.AzureKeyVault,
          ServerKeyName = "mykeyvault_mykey_abc123",
          AutoRotationEnabled = true
      };
      
      var protector = server.GetEncryptionProtector();
      await protector.CreateOrUpdateAsync(WaitUntil.Completed, protectorData);
      ```
      
  • SKILL.md 10.3 KB
    ---
    name: azure-resource-manager-sql-dotnet
    description: |
      Azure Resource Manager SDK for Azure SQL in .NET. Use for MANAGEMENT PLANE operations: creating/managing SQL servers, databases, elastic pools, firewall rules, and failover groups via Azure Resource Manager. NOT for data plane operations (executing queries) - use Microsoft.Data.SqlClient for that. Triggers: "SQL server", "create SQL database", "manage SQL resources", "ARM SQL", "SqlServerResource", "provision Azure SQL", "elastic pool", "firewall rule".
    license: MIT
    metadata:
      author: Microsoft
      version: "1.0.0"
      package: Azure.ResourceManager.Sql
    ---
    
    # Azure.ResourceManager.Sql (.NET)
    
    Management plane SDK for provisioning and managing Azure SQL resources via Azure Resource Manager.
    
    > **⚠️ Management vs Data Plane**
    > - **This SDK (Azure.ResourceManager.Sql)**: Create servers, databases, elastic pools, configure firewall rules, manage failover groups
    > - **Data Plane SDK (Microsoft.Data.SqlClient)**: Execute queries, stored procedures, manage connections
    
    ## Installation
    
    ```bash
    dotnet add package Azure.ResourceManager.Sql
    dotnet add package Azure.Identity
    ```
    
    **Current Versions**: Stable v1.3.0, Preview v1.4.0-beta.3
    
    ## Environment Variables
    
    ```bash
    AZURE_SUBSCRIPTION_ID=<your-subscription-id>  # Required: Azure subscription ID
    AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production
    AZURE_TENANT_ID=<tenant-id>  # For service principal auth (optional)
    AZURE_CLIENT_ID=<client-id>  # For service principal auth (optional)
    AZURE_CLIENT_SECRET=<client-secret>  # For service principal auth (optional)
    ```
    
    ## Authentication
    
    ```csharp
    using Azure.Identity;
    using Azure.ResourceManager;
    using Azure.ResourceManager.Sql;
    
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    var credential = new DefaultAzureCredential(
        DefaultAzureCredential.DefaultEnvironmentVariableName
    );
    // Or use a specific credential directly in production:
    // See https://learn.microsoft.com/dotnet/api/overview/azure/identity-readme?view=azure-dotnet#credential-classes
    // var credential = new ManagedIdentityCredential();
    var armClient = new ArmClient(credential);
    
    // Get subscription
    var subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID");
    var subscription = armClient.GetSubscriptionResource(
        new ResourceIdentifier($"/subscriptions/{subscriptionId}"));
    ```
    
    ## Resource Hierarchy
    
    ```
    ArmClient
    └── SubscriptionResource
        └── ResourceGroupResource
            └── SqlServerResource
                ├── SqlDatabaseResource
                ├── ElasticPoolResource
                │   └── ElasticPoolDatabaseResource
                ├── SqlFirewallRuleResource
                ├── FailoverGroupResource
                ├── ServerBlobAuditingPolicyResource
                ├── EncryptionProtectorResource
                └── VirtualNetworkRuleResource
    ```
    
    ## Core Workflow
    
    ### 1. Create SQL Server
    
    ```csharp
    using Azure.ResourceManager.Sql;
    using Azure.ResourceManager.Sql.Models;
    
    // Get resource group
    var resourceGroup = await subscription
        .GetResourceGroupAsync("my-resource-group");
    
    // Define server
    var serverData = new SqlServerData(AzureLocation.EastUS)
    {
        AdministratorLogin = "sqladmin",
        AdministratorLoginPassword = "YourSecurePassword123!",
        Version = "12.0",
        MinimalTlsVersion = SqlMinimalTlsVersion.Tls1_2,
        PublicNetworkAccess = ServerNetworkAccessFlag.Enabled
    };
    
    // Create server (long-running operation)
    var serverCollection = resourceGroup.Value.GetSqlServers();
    var operation = await serverCollection.CreateOrUpdateAsync(
        WaitUntil.Completed,
        "my-sql-server",
        serverData);
    
    SqlServerResource server = operation.Value;
    ```
    
    ### 2. Create SQL Database
    
    ```csharp
    var databaseData = new SqlDatabaseData(AzureLocation.EastUS)
    {
        Sku = new SqlSku("S0") { Tier = "Standard" },
        MaxSizeBytes = 2L * 1024 * 1024 * 1024, // 2 GB
        Collation = "SQL_Latin1_General_CP1_CI_AS",
        RequestedBackupStorageRedundancy = SqlBackupStorageRedundancy.Local
    };
    
    var databaseCollection = server.GetSqlDatabases();
    var dbOperation = await databaseCollection.CreateOrUpdateAsync(
        WaitUntil.Completed,
        "my-database",
        databaseData);
    
    SqlDatabaseResource database = dbOperation.Value;
    ```
    
    ### 3. Create Elastic Pool
    
    ```csharp
    var poolData = new ElasticPoolData(AzureLocation.EastUS)
    {
        Sku = new SqlSku("StandardPool")
        {
            Tier = "Standard",
            Capacity = 100 // 100 eDTUs
        },
        PerDatabaseSettings = new ElasticPoolPerDatabaseSettings
        {
            MinCapacity = 0,
            MaxCapacity = 100
        }
    };
    
    var poolCollection = server.GetElasticPools();
    var poolOperation = await poolCollection.CreateOrUpdateAsync(
        WaitUntil.Completed,
        "my-elastic-pool",
        poolData);
    
    ElasticPoolResource pool = poolOperation.Value;
    ```
    
    ### 4. Add Database to Elastic Pool
    
    ```csharp
    var databaseData = new SqlDatabaseData(AzureLocation.EastUS)
    {
        ElasticPoolId = pool.Id
    };
    
    await databaseCollection.CreateOrUpdateAsync(
        WaitUntil.Completed,
        "pooled-database",
        databaseData);
    ```
    
    ### 5. Configure Firewall Rules
    
    ```csharp
    // Allow Azure services
    var azureServicesRule = new SqlFirewallRuleData
    {
        StartIPAddress = "0.0.0.0",
        EndIPAddress = "0.0.0.0"
    };
    
    var firewallCollection = server.GetSqlFirewallRules();
    await firewallCollection.CreateOrUpdateAsync(
        WaitUntil.Completed,
        "AllowAzureServices",
        azureServicesRule);
    
    // Allow specific IP range
    var clientRule = new SqlFirewallRuleData
    {
        StartIPAddress = "203.0.113.0",
        EndIPAddress = "203.0.113.255"
    };
    
    await firewallCollection.CreateOrUpdateAsync(
        WaitUntil.Completed,
        "AllowClientIPs",
        clientRule);
    ```
    
    ### 6. List Resources
    
    ```csharp
    // List all servers in subscription
    await foreach (var srv in subscription.GetSqlServersAsync())
    {
        Console.WriteLine($"Server: {srv.Data.Name} in {srv.Data.Location}");
    }
    
    // List databases in a server
    await foreach (var db in server.GetSqlDatabases())
    {
        Console.WriteLine($"Database: {db.Data.Name}, SKU: {db.Data.Sku?.Name}");
    }
    
    // List elastic pools
    await foreach (var ep in server.GetElasticPools())
    {
        Console.WriteLine($"Pool: {ep.Data.Name}, DTU: {ep.Data.Sku?.Capacity}");
    }
    ```
    
    ### 7. Get Connection String
    
    ```csharp
    // Build connection string (server FQDN is predictable)
    var serverFqdn = $"{server.Data.Name}.database.windows.net";
    var connectionString = $"Server=tcp:{serverFqdn},1433;" +
        $"Initial Catalog={database.Data.Name};" +
        "Persist Security Info=False;" +
        $"User ID={server.Data.AdministratorLogin};" +
        "Password=<your-password>;" +
        "MultipleActiveResultSets=False;" +
        "Encrypt=True;" +
        "TrustServerCertificate=False;" +
        "Connection Timeout=30;";
    ```
    
    ## Key Types Reference
    
    | Type | Purpose |
    |------|---------|
    | `ArmClient` | Entry point for all ARM operations |
    | `SqlServerResource` | Represents an Azure SQL server |
    | `SqlServerCollection` | Collection for server CRUD |
    | `SqlDatabaseResource` | Represents a SQL database |
    | `SqlDatabaseCollection` | Collection for database CRUD |
    | `ElasticPoolResource` | Represents an elastic pool |
    | `ElasticPoolCollection` | Collection for elastic pool CRUD |
    | `SqlFirewallRuleResource` | Represents a firewall rule |
    | `SqlFirewallRuleCollection` | Collection for firewall rule CRUD |
    | `SqlServerData` | Server creation/update payload |
    | `SqlDatabaseData` | Database creation/update payload |
    | `ElasticPoolData` | Elastic pool creation/update payload |
    | `SqlFirewallRuleData` | Firewall rule creation/update payload |
    | `SqlSku` | SKU configuration (tier, capacity) |
    
    ## Common SKUs
    
    ### Database SKUs
    
    | SKU Name | Tier | Description |
    |----------|------|-------------|
    | `Basic` | Basic | 5 DTUs, 2 GB max |
    | `S0`-`S12` | Standard | 10-3000 DTUs |
    | `P1`-`P15` | Premium | 125-4000 DTUs |
    | `GP_Gen5_2` | GeneralPurpose | vCore-based, 2 vCores |
    | `BC_Gen5_2` | BusinessCritical | vCore-based, 2 vCores |
    | `HS_Gen5_2` | Hyperscale | vCore-based, 2 vCores |
    
    ### Elastic Pool SKUs
    
    | SKU Name | Tier | Description |
    |----------|------|-------------|
    | `BasicPool` | Basic | 50-1600 eDTUs |
    | `StandardPool` | Standard | 50-3000 eDTUs |
    | `PremiumPool` | Premium | 125-4000 eDTUs |
    | `GP_Gen5_2` | GeneralPurpose | vCore-based |
    | `BC_Gen5_2` | BusinessCritical | vCore-based |
    
    ## Best Practices
    
    1. **Use `WaitUntil.Completed`** for operations that must finish before proceeding
    2. **Use `WaitUntil.Started`** when you want to poll manually or run operations in parallel
    3. **Always use `DefaultAzureCredential`** — never hardcode passwords in production
    4. **Handle `RequestFailedException`** for ARM API errors
    5. **Use `CreateOrUpdateAsync`** for idempotent operations
    6. **Navigate hierarchy** via `Get*` methods (e.g., `server.GetSqlDatabases()`)
    7. **Use elastic pools** for cost optimization when managing multiple databases
    8. **Configure firewall rules** before attempting connections
    
    ## Error Handling
    
    ```csharp
    using Azure;
    
    try
    {
        var operation = await serverCollection.CreateOrUpdateAsync(
            WaitUntil.Completed, serverName, serverData);
    }
    catch (RequestFailedException ex) when (ex.Status == 409)
    {
        Console.WriteLine("Server already exists");
    }
    catch (RequestFailedException ex) when (ex.Status == 400)
    {
        Console.WriteLine($"Invalid request: {ex.Message}");
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"ARM Error: {ex.Status} - {ex.ErrorCode}: {ex.Message}");
    }
    ```
    
    ## Reference Files
    
    | File | When to Read |
    |------|--------------|
    | [references/server-management.md](references/server-management.md) | Server CRUD, admin credentials, Azure AD auth, networking |
    | [references/database-operations.md](references/database-operations.md) | Database CRUD, scaling, backup, restore, copy |
    | [references/elastic-pools.md](references/elastic-pools.md) | Pool management, adding/removing databases, scaling |
    
    ## Related SDKs
    
    | SDK | Purpose | Install |
    |-----|---------|---------|
    | `Microsoft.Data.SqlClient` | Data plane (execute queries, stored procedures) | `dotnet add package Microsoft.Data.SqlClient` |
    | `Azure.ResourceManager.Sql` | Management plane (this SDK) | `dotnet add package Azure.ResourceManager.Sql` |
    | `Microsoft.EntityFrameworkCore.SqlServer` | ORM for SQL Server | `dotnet add package Microsoft.EntityFrameworkCore.SqlServer` |
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related