使用Azure.Data.Tables .NET SDK保存Dictionary触发NotSupportedException问题
Azure.Data.Tables 保存含Dictionary属性实体报错解决方案
报错原因
Azure Table Storage 以及 Cosmos DB Table API 底层仅支持EDM标准定义的基础数据类型(字符串、布尔、数值、GUID、DateTime、二进制等),不支持直接存储Dictionary这类集合复杂类型。
你之前使用Cosmos DB SQL API可以正常保存,是因为SQL API原生支持完整JSON结构的复杂类型存储,和Azure.Data.Tables库的序列化限制无关,也和System.Text.Json本身是否支持Dictionary序列化无关,是Table类存储的类型限制导致的报错。
可用解决方案
方案一:字典转JSON字符串存储(最简便)
新增字符串属性做中转,字典属性标记为忽略序列化,读写时自动做序列化/反序列化转换,代码示例如下:
using System.Runtime.Serialization; using System.Text.Json; class PersistedPerson : ITableEntity { // ITableEntity 必要属性 public string PartitionKey { get; set; } public string RowKey { get; set; } public DateTimeOffset? Timestamp { get; set; } public ETag ETag { get; set; } public string Name { get; init; } [IgnoreDataMember] public Dictionary<Guid, Guid> SomeDictionary { get; init; } = new(); // 实际落库属性 public string SomeDictionaryStorage { get => JsonSerializer.Serialize(SomeDictionary); set => SomeDictionary = string.IsNullOrWhiteSpace(value) ? new() : JsonSerializer.Deserialize<Dictionary<Guid, Guid>>(value); } }
方案二:自定义实体序列化逻辑
如果存在多个复杂类型属性,可以实现ITableEntity的读写方法统一控制序列化规则,示例如下:
using Microsoft.Azure.Cosmos.Table; using System.Text.Json; class PersistedPerson : ITableEntity { public string PartitionKey { get; set; } public string RowKey { get; set; } public DateTimeOffset? Timestamp { get; set; } public ETag ETag { get; set; } public string Name { get; init; } public Dictionary<Guid, Guid> SomeDictionary { get; init; } = new(); public void WriteEntity(IDictionary<string, object> properties, OperationContext operationContext) { properties.Add(nameof(Name), Name); properties.Add(nameof(SomeDictionary), JsonSerializer.Serialize(SomeDictionary)); } public void ReadEntity(IDictionary<string, object> properties, OperationContext operationContext) { Name = properties.TryGetValue(nameof(Name), out var nameVal) ? nameVal as string : default; if (properties.TryGetValue(nameof(SomeDictionary), out var dictVal) && dictVal is string dictJson) { SomeDictionary = JsonSerializer.Deserialize<Dictionary<Guid, Guid>>(dictJson) ?? new(); } } }
方案三:切换存储服务
如果业务大量依赖复杂JSON结构存储,不想做额外的序列化改造,可以直接使用Cosmos DB SQL API,该场景下无需修改模型即可正常运行。
内容的提问来源于stack exchange,提问作者Jason Shave
相关产品推荐
相关产品推荐

