如何使用C#或X++动态读取D365运营AOT中的表名与属性
动态读取Dynamics 365 Finance & Operations AOT中的表名称及属性(C#和X++实现)
我来帮你梳理下用X++和C#动态读取D365 F&O AOT中表名称及属性的具体实现方法,这俩场景我都做过不少,直接上干货:
X++ 实现方案
X++作为D365 F&O的原生开发语言,直接访问AOT元数据是最直接高效的,核心就是利用SysDictTable这个系统类来遍历表并获取属性。
示例代码
static void readAOTTablesAndAttributes(Args _args) { SysDictTable sysDictTable; TableId tableId; DictField dictField; int fieldIdx; // 遍历所有注册的表ID范围 for (tableId = tablenum(FirstTable); tableId <= tablenum(LastTable); tableId++) { sysDictTable = SysDictTable::newTableId(tableId); // 可选:排除系统表,只保留自定义/业务表 if (sysDictTable && !sysDictTable.isSystemTable()) { info(strFmt("表名称: %1, 显示标签: %2, 表ID: %3", sysDictTable.name(), sysDictTable.label(), tableId)); // 遍历表的所有字段,获取字段属性 for (fieldIdx = 1; fieldIdx <= sysDictTable.fieldCnt(); fieldIdx++) { dictField = sysDictTable.fieldObject(fieldIdx); if (dictField) { info(strFmt(" 字段名: %1, 显示标签: %2, 数据类型: %3", dictField.name(), dictField.label(), enum2Str(dictField.typeId()))); } } } } }
关键细节
SysDictTable封装了表的所有元数据,通过表ID实例化后,能获取表的名称、显示标签、表组(比如临时表、普通表)、字段数量等信息。- 如果需要过滤特定类型的表,比如只看临时表,可以用
sysDictTable.isTmpTable();或者通过sysDictTable.tableGroup()判断表所属的分组。 - 字段的更多属性(比如是否必填、字段长度)可以通过
DictField的其他方法获取,比如dictField.mandatory()、dictField.stringSize()。
C# 实现方案
C#作为外部语言,没法直接访问D365的AOT,得通过官方提供的API来获取元数据。最通用的方式是OData Metadata API,不管是云环境还是内部部署都能兼容,而且配置简单。
方法1:解析OData Metadata文档
D365的OData服务提供了$metadata端点,返回的XML文档包含了所有实体(对应AOT中的表)的完整元数据,我们只需要解析这个XML就能拿到表和字段信息。
示例代码
using System; using System.Net.Http; using System.Xml.Linq; using System.Threading.Tasks; class D365TableMetadataReader { static async Task Main(string[] args) { // 替换成你的D365环境地址、账号密码 string d365BaseUrl = "https://your-d365-environment-url.cloudax.dynamics.com/data/"; string metadataUrl = $"{d365BaseUrl}$metadata"; string username = "your-account@domain.com"; string password = "your-password"; using (HttpClient client = new HttpClient()) { // 配置身份验证:生产环境建议用OAuth 2.0,这里用基本认证做演示 var authBytes = System.Text.Encoding.ASCII.GetBytes($"{username}:{password}"); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue( "Basic", Convert.ToBase64String(authBytes)); // 获取元数据文档 var response = await client.GetAsync(metadataUrl); response.EnsureSuccessStatusCode(); string metadataXml = await response.Content.ReadAsStringAsync(); // 解析XML提取表和字段信息 XDocument doc = XDocument.Parse(metadataXml); XNamespace edmNs = "http://docs.oasis-open.org/odata/ns/edm"; foreach (var entityType in doc.Descendants(edmNs + "EntityType")) { string tableName = entityType.Attribute("Name").Value; Console.WriteLine($"表名称: {tableName}"); // 遍历字段属性 foreach (var property in entityType.Descendants(edmNs + "Property")) { string fieldName = property.Attribute("Name").Value; string fieldType = property.Attribute("Type").Value; Console.WriteLine($" 字段名: {fieldName}, 数据类型: {fieldType}"); } } } } }
方法2:调用EntityDefinitions API(获取更详细属性)
如果需要获取表的显示标签、描述等更丰富的属性,可以直接调用EntityDefinitions API,返回的JSON包含更完整的元数据:
// 示例请求地址,可通过$filter过滤特定表 string entityDefUrl = $"{d365BaseUrl}EntityDefinitions?$filter=SchemaName eq 'CustTable'"; // 发送GET请求后解析JSON即可拿到表的标签、描述等信息
关键细节
- 生产环境绝对不要用基本认证,一定要用Azure AD OAuth 2.0,需要在Azure AD中注册应用并配置D365的权限。
- OData中的
EntityType对应AOT中的表,Property对应表的字段,还能获取主键、导航属性等关联信息。 - 如果是内部部署环境,也可以使用Dynamics AX Business Connector,但这个方式在云环境中已经被淘汰,优先用OData方案。
内容的提问来源于stack exchange,提问作者karthikeyan




