news 2026/10/21 2:18:59

使用 Azure.ResourceManager.Sql (.NET) 管理平面 SDK 编排 Azure SQL 资源

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Azure.ResourceManager.Sql (.NET) 管理平面 SDK 编排 Azure SQL 资源

使用 Azure.ResourceManager.Sql (.NET) 管理平面 SDK 编排 Azure SQL 资源

【免费下载链接】agentic-awesome-skillsAAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.项目地址: https://gitcode.com/GitHub_Trending/an/agentic-awesome-skills

导读

本文基于 agentic-awesome-skills 仓库中的azure-resource-manager-sql-dotnet技能文档,系统讲解在 .NET 应用中通过Azure.ResourceManager.Sql(Azure Resource Manager 管理平面 SDK)以编程方式创建、配置与治理 Azure SQL Server、数据库、弹性池、防火墙规则与故障转移组等资源。你将掌握从环境配置、DefaultAzureCredential认证、资源层级导航,到完整 CRUD 工作流、SKU 选型、错误处理与生产级最佳实践的一整套实操能力,可直接用于编写自动化部署脚本、运维工具或 CI/CD 中的 SQL 资源编排步骤。

管理平面与数据平面:先分清 SDK 的边界

在动手写代码前,必须先理解Azure.ResourceManager.Sql在整个 Azure SQL 体系中的定位。该技能文档开篇就明确强调了管理平面(Management Plane)与数据平面(Data Plane)的严格区分:

  • 管理平面 SDK(Azure.ResourceManager.Sql):负责“建”和“管”资源——创建 SQL Server、创建数据库、管理弹性池、配置防火墙规则、管理故障转移组、设置审计策略与透明数据加密(TDE)等。它操作的是一整套 ARM 资源对象。
  • 数据平面 SDK(Microsoft.Data.SqlClient):负责“用”数据——建立连接、执行查询、调用存储过程、管理事务。它直接面向*.database.windows.net上的数据库引擎。

两者的职责边界决定了它们不能互相替代:你无法用Azure.ResourceManager.Sql执行SELECT,也无法用Microsoft.Data.SqlClient创建弹性池。实际项目中通常组合使用:先用管理平面 SDK 完成资源编排,再用数据平面 SDK 执行初始化脚本或业务查询。仓库中与该技能同属 Azure 系列的 azure-sql 等技能文档,可帮助你进一步理解 Azure SQL 生态中各 SDK 的协作关系。

安装与环境变量配置

安装 NuGet 包

dotnet add package Azure.ResourceManager.Sql dotnet add package Azure.Identity
  • Azure.ResourceManager.Sql:本技能的核心包,提供全部 SQL 管理资源类型。
  • Azure.Identity:提供DefaultAzureCredential等身份认证组件,是使用 ARM SDK 的必需配套。

技能文档标注的当前版本信息为Stable v1.3.0、Preview v1.4.0-beta.3。安装前可通过dotnet list package或 NuGet 官方源确认实际可用版本,并优先选择与你的 .NET 目标框架(如 net8.0/net9.0)兼容的稳定版本。

环境变量

AZURE_SUBSCRIPTION_ID=<your-subscription-id> # For service principal auth (optional) AZURE_TENANT_ID=<tenant-id> AZURE_CLIENT_ID=<client-id> AZURE_CLIENT_SECRET=<client-secret>
  • AZURE_SUBSCRIPTION_ID:必填。用于构造订阅资源标识符(/subscriptions/{id}),是后续一切资源操作的作用域起点。
  • AZURE_TENANT_ID/AZURE_CLIENT_ID/AZURE_CLIENT_SECRET:可选,仅在采用服务主体(Service Principal)认证时需要。DefaultAzureCredential会自动读取这些变量完成服务主体认证;若在本地开发环境,则优先使用 Visual Studio / Azure CLI 登录凭据,无需配置这三项。

认证:始终使用 DefaultAzureCredential

管理平面 SDK 的入口是ArmClient,而构建它的第一步是获得一个可信凭据:

using Azure.Identity; using Azure.ResourceManager; using Azure.ResourceManager.Sql; // Always use DefaultAzureCredential var credential = new DefaultAzureCredential(); var armClient = new ArmClient(credential); // Get subscription var subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); var subscription = armClient.GetSubscriptionResource( new ResourceIdentifier($"/subscriptions/{subscriptionId}"));

几点需要理解的关键机制:

  1. DefaultAzureCredential的链式尝试:它会按顺序尝试多种凭据来源(环境变量服务主体 → Azure CLI → Visual Studio → Managed Identity 等),从而让同一段代码在本地开发、CI/CD 与 Azure 云环境之间无缝切换,这正是技能文档强调“永远不要在生产环境硬编码密码”的原因。
  2. ResourceIdentifier:ARM 中所有资源都有全局唯一的 ARM ID,形如/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Sql/servers/{name}。SDK 通过ResourceIdentifier解析这些 ID 并在资源之间导航。
  3. 权限模型:操作 SQL 资源需要订阅/资源组级别的 ARM 权限(如 Contributor 或自定义 RBAC 角色),这与数据平面的数据库用户权限(login/user 体系)是完全独立的两套授权。

资源层级:从 ArmClient 向下导航

ARM SDK 的核心设计是层级化集合模型——每一层资源都通过其父资源的Get{Child}s()方法(即集合)访问。技能文档给出的层级如下:

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

理解这条链的意义在于:集合(*Collection)负责 CRUD,资源(*Resource)负责实例操作与再向下导航。例如要创建一个数据库,必须先拿到SqlServerResource,再通过server.GetSqlDatabases()获得SqlDatabaseCollection执行CreateOrUpdateAsync。这种“先定位父资源、再操作子资源”的模式贯穿整个 SDK,与 azure-resource-manager-cosmosdb-dotnet 等同系列管理平面技能一致,学习成本可以横向复用。

核心工作流:七个典型操作全解析

以下代码均来自技能文档,并补充了参数含义、取值范围与运行前提,可直接作为脚本骨架。

1. 创建 SQL Server

using System; 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 = Environment.GetEnvironmentVariable("SQL_ADMIN_PASSWORD") ?? throw new InvalidOperationException("SQL_ADMIN_PASSWORD is required"), 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;
  • 前提:my-resource-group必须已存在;若不存在,可先用resourceGroupCollection.CreateOrUpdateAsync创建资源组。
  • AdministratorLoginPassword:建议从环境变量或密钥库(如 Azure Key Vault)读取,文档代码用?? throw强制要求该变量存在,避免空密码下发。
  • Version = "12.0":当前 Azure SQL 逻辑服务器的引擎版本。
  • MinimalTlsVersion = SqlMinimalTlsVersion.Tls1_2:强制最低 TLS 1.2,满足安全基线要求。
  • PublicNetworkAccess:控制是否允许公网访问;生产环境若需完全私网化可设为Disabled并配合VirtualNetworkRuleResource使用。
  • 长时运行操作(LRO):CreateOrUpdateAsync返回一个ArmOperation,WaitUntil.Completed表示阻塞等待操作完成;WaitUntil.Started则立即返回、由调用方手动轮询或并行执行。

2. 创建 SQL 数据库

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;
  • Sku与Tier:决定数据库的性能层与计费模型(见下文 SKU 参考表)。S0属于按 DTU 计费的 Standard 层;若采用 vCore 模型,则使用GP_Gen5_2这类 SKU。
  • MaxSizeBytes:数据库最大容量,单位为字节;2L * 1024 * 1024 * 1024即 2 GB。注意 Basic/Standard 层的容量上限受 SKU 约束。
  • Collation:默认SQL_Latin1_General_CP1_CI_AS(不区分大小写);创建后不可修改,务必提前规划。
  • RequestedBackupStorageRedundancy:备份存储冗余策略(Local/Zone/Geo),影响可用性与成本。

3. 创建弹性池

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;
  • Capacity:池的总容量,Standard 层单位为 eDTU(弹性 DTU);此处 100 表示池共享 100 eDTU。
  • PerDatabaseSettings:单库在池内可占用的容量区间(MinCapacity–MaxCapacity),让池内数据库弹性伸缩而无需独立预配资源。若省略,SDK 会使用默认的最小/最大设置。

4. 将数据库加入弹性池

var databaseData = new SqlDatabaseData(AzureLocation.EastUS) { ElasticPoolId = pool.Id }; await databaseCollection.CreateOrUpdateAsync( WaitUntil.Completed, "pooled-database", databaseData);

将ElasticPoolId指向已有池即可把数据库移入池内,这是弹性池成本优化的核心用法——多个低负载数据库共享一份池容量,避免各自按独立 SKU 计费。同样地,将该字段置为null即可把数据库移出池。

5. 配置防火墙规则

// 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);
  • 0.0.0.0–0.0.0.0是特殊规则:表示“允许所有 Azure 服务访问”,并非真正开放全公网;通常在数据平面无法连通时作为排查第一步。
  • 客户端规则应遵循最小权限原则,仅放行实际出口 IP 区间(示例使用文档段203.0.113.0/24仅作演示,请替换为真实 IP)。
  • 技能文档特别提示:在尝试建立任何连接之前,先配置好防火墙规则,否则数据平面连接会因 IP 未放行而被拒绝。

6. 枚举资源

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

GetSqlServersAsync()是订阅级别的便捷方法(跨资源组枚举),而server.GetSqlDatabases()/server.GetElasticPools()是服务器级别枚举。所有枚举方法都支持await foreach异步流式遍历,返回的资源对象通过.Data暴露属性(如Name、Location、Sku)。

7. 生成连接字符串

// 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;";
  • 逻辑服务器 FQDN 遵循{server-name}.database.windows.net的确定性规则,因此可由资源名直接拼出。
  • Encrypt=True+TrustServerCertificate=False是面向生产的安全组合(强制 TLS 加密且不信任自签名证书),与前面MinimalTlsVersion = Tls1_2的设置形成闭环。
  • User ID/Password为 SQL 登录凭据;若改用 Microsoft Entra ID(Azure AD)认证,可替换为Authentication=Active Directory Default等项并使用Microsoft.Data.SqlClient的对应认证模式。

关键类型参考

技能文档整理的核心类型及其职责如下,理解它们能显著降低上手成本:

TypePurpose
ArmClientEntry point for all ARM operations
SqlServerResourceRepresents an Azure SQL server
SqlServerCollectionCollection for server CRUD
SqlDatabaseResourceRepresents a SQL database
SqlDatabaseCollectionCollection for database CRUD
ElasticPoolResourceRepresents an elastic pool
ElasticPoolCollectionCollection for elastic pool CRUD
SqlFirewallRuleResourceRepresents a firewall rule
SqlFirewallRuleCollectionCollection for firewall rule CRUD
SqlServerDataServer creation/update payload
SqlDatabaseDataDatabase creation/update payload
ElasticPoolDataElastic pool creation/update payload
SqlFirewallRuleDataFirewall rule creation/update payload
SqlSkuSKU configuration (tier, capacity)

命名规律:{资源}Resource(实例)、{资源}Collection(集合)、{资源}Data(创建/更新负载)三件套构成了该 SDK 几乎全部资源类型的统一模式,掌握此规律即可举一反三地使用FailoverGroupResource、ServerBlobAuditingPolicyResource、EncryptionProtectorResource、VirtualNetworkRuleResource等其余类型。

SKU 选型参考

数据库 SKU

SKU NameTierDescription
BasicBasic5 DTUs, 2 GB max
S0–S12Standard10-3000 DTUs
P1–P15Premium125-4000 DTUs
GP_Gen5_2GeneralPurposevCore-based, 2 vCores
BC_Gen5_2BusinessCriticalvCore-based, 2 vCores
HS_Gen5_2HyperscalevCore-based, 2 vCores

弹性池 SKU

SKU NameTierDescription
BasicPoolBasic50-1600 eDTUs
StandardPoolStandard50-3000 eDTUs
PremiumPoolPremium125-4000 eDTUs
GP_Gen5_2GeneralPurposevCore-based
BC_Gen5_2BusinessCriticalvCore-based

选型要点:

  • DTU 模型(Basic/Standard/Premium及*Pool):计费简单,适合中小型工作负载;S0 起步 10 DTU,Premium 最高 4000 DTU。
  • vCore 模型(GP_Gen5_2/BC_Gen5_2/HS_Gen5_2):按核数与内存计费,支持预留实例折扣,Gen5表示硬件代次、_2表示 2 个 vCore。Hyperscale(HS_)面向超大数据库与高并发读取场景。
  • 弹性池以 eDTU(弹性 DTU)为单位,PerDatabaseSettings决定池内单库容量区间。实际选型应以工作负载基准测试与成本测算为准,而非仅凭 SKU 名称。

最佳实践清单

技能文档给出的八条实践原则,对应到本文各环节如下:

  1. WaitUntil.Completed:必须在操作真正完成后再继续执行的场景(如创建服务器后再创建数据库),用它阻塞等待。
  2. WaitUntil.Started:需要手动轮询或并行执行多个创建任务时使用,避免串行等待拖慢整体编排。
  3. 始终使用DefaultAzureCredential:生产环境绝不硬编码密码;本地用 IDE/CLI 凭据,云端用托管身份,CI 用服务主体。
  4. 处理RequestFailedException:ARM API 的绝大多数错误都以该异常抛出,必须显式捕获(见下文)。
  5. 使用CreateOrUpdateAsync实现幂等:同一资源重复调用不会报“已存在”,而是执行更新语义,天然适合重试与状态收敛。
  6. 通过Get*方法导航层级:不要手工拼接子资源 ID,统一用server.GetSqlDatabases()这类方法获取集合,保证路径正确。
  7. 多数据库用弹性池降本:低利用率的多数据库共享池容量,是明显的成本优化手段。
  8. 先配防火墙再连数据平面:避免连接超时排查时误判问题根因。

错误处理:读懂 ARM 异常

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}"); }
  • ex.Status:HTTP 状态码,是快速定位问题的第一线索:
    • 400Bad Request:请求参数非法(如 SKU 与层级不匹配、容量超出配额);
    • 404Not Found:目标资源/资源组不存在;
    • 409Conflict:资源已存在(结合CreateOrUpdateAsync的幂等语义,通常可忽略或记录后继续);
    • 403Forbidden:RBAC 权限不足,需检查服务主体/身份的角色分配。
  • ex.ErrorCode:ARM 返回的机器可读错误码,可用于程序化分支或写入监控告警。
  • 配合WaitUntil.Started的轮询场景,还应关注轮询过程中的中间状态,并对超时做兜底处理。

相关 SDK 与延伸阅读

SDKPurposeInstall
Microsoft.Data.SqlClientData plane (execute queries, stored procedures)dotnet add package Microsoft.Data.SqlClient
Azure.ResourceManager.SqlManagement plane (this SDK)dotnet add package Azure.ResourceManager.Sql
Microsoft.EntityFrameworkCore.SqlServerORM for SQL Serverdotnet add package Microsoft.EntityFrameworkCore.SqlServer

典型组合:管理平面 SDK 完成“建库建表空间”等资源编排 → 数据平面 SDK 执行初始化 DDL/DML → ORM(EF Core)承载业务数据访问。三者职责互补,构成完整的 Azure SQL .NET 技术栈。

技能文档还规划了配套的参考文件目录(references/server-management.md、references/database-operations.md、references/elastic-pools.md),分别深入覆盖服务器 CRUD 与管理员凭据/Azure AD 认证/网络、数据库 CRUD 与扩容/备份/还原/复制、弹性池管理与扩缩容等进阶主题;本技能当前版本暂未附带这些文件,需要进阶场景时可结合 Azure 官方文档与仓库中同系列技能(如 azure-sql、azure-resource-manager-cosmosdb-dotnet)交叉参考。

使用边界与注意事项

  • 适用场景:本技能面向明确的 Azure SQL 资源管理平面编排任务(创建/更新/查询服务器、数据库、弹性池、防火墙、故障转移组等),当任务与上述范围匹配时使用。
  • 不可替代验证:脚本产出不能替代针对具体环境的验证、测试与专家评审——尤其是网络策略、RBAC 权限与成本估算,必须结合目标订阅实际情况确认。
  • 信息不足时及时澄清:当缺少必要的输入参数(如订阅 ID、资源组名、SQL 管理员密码)、权限、安全边界或成功标准时,应停止执行并向用户确认,避免在错误假设下产生破坏性变更。

本文所有代码与结论均以仓库中 azure-resource-manager-sql-dotnet 技能文档(plugins/agentic-awesome-skills-claude/skills/azure-resource-manager-sql-dotnet/SKILL.md与之内容一致)为事实基础,示例中的占位值(IP、密码、资源名)需按实际环境替换后方可运行。

【免费下载链接】agentic-awesome-skillsAAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.项目地址: https://gitcode.com/GitHub_Trending/an/agentic-awesome-skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 2:15:14

STM32实战:手写DS1302实时时钟驱动与掉电保持

1. 项目概述&#xff1a;为什么是DS13021.1 核心需求解析老规矩&#xff0c;先聊聊这个项目解决的到底是什么问题。单片机的定时器做时间戳、倒计时都够用&#xff0c;但一断电时间就丢了&#xff0c;每次上电都要重新校准&#xff0c;这在很多设备里是没法接受的。实时时钟芯片…

作者头像 李华
网站建设 2026/10/21 2:14:28

agent-qa-result-triage - SKILL

name: agent-qa-result-triage description: “Triage failed Agent QA runs with MCP evidence, artifacts, logs, fixed failure categories, confidence, and actionable next steps.” category: testing risk: safe source: https://github.com/vostride/agent-qa/tree/ma…

作者头像 李华
网站建设 2026/10/21 2:14:25

[DeepSeek Harness插件内核-11]这算Cordis一个大BUG吗?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华