我有一个对象Record
,它有一个Name
和一个Theme
。
主题是嵌入在类型化类中的键值对,如"01"-"运动"、"02"-"家庭"等
我有一个这样的对象:
public class DescriptionEntity : TableEntity
{
public string Description { get; set; }
public string Key { get { return RowKey; } set { RowKey = value; } }
public DescriptionEntity() { }
}
public class Theme : DescriptionEntity
{
}
/* The Record has a "string" and a "Theme" property */
public class Record : TableEntity
{
[...]
public string Name { get; set; }
public Theme Theme { get; set; }
}
问题是当我尝试从 Azure 表中加载该记录时,如下所示:
var record = await repository.GetTableEntityAsync<Record>(id, RecordConst.RecordPartitionKey);
// ..........................
public async Task<T> GetTableEntityAsync<T>(string rowKey, string partitionKey) where T : ITableEntity, new()
{
var table = GetTable<T>();
TableQuery<T> query = new TableQuery<T>().Where(
TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey),
TableOperators.And,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, rowKey))).Take(1);
var result = new T();
TableContinuationToken continuationToken = null;
do
{
Task<TableQuerySegment<T>> querySegment = table.ExecuteQuerySegmentedAsync(query, continuationToken);
TableQuerySegment<T> segment = await querySegment;
result = segment.FirstOrDefault();
continuationToken = segment.ContinuationToken;
} while (continuationToken != null);
return result;
}
我获得了record.Name
,但record.Theme
始终保持"null",不从"记录"表加载,就像:
Partition Key Name Theme
"record" "x" "test" "01"
也在我的"主题"表中,我有
Partition Key Description
"en" "01" "Sport"
我试图将构造函数添加到"主题"类中
public class Theme : DescriptionEntity
{
public Theme() : base() { }
public Theme(string key) : base(key) { }
}
但这并没有改变结果...
有没有办法明确地说"获取字符串"主题"并使用new Theme(string)
来创建Theme
属性">
你可能已经知道 Azure 表是一个Key/Value
存储。但是,要考虑的要点是Value
可以是以下预定义类型:String
、Int32
、Int64
、DateTimeOffset
、Double
、GUID
和Binary
。
在您的情况下,属性Theme
的值属于Theme
类型,它不是受支持的类型之一,因此存储客户端库不会反序列化它,因此您获得null
值。
一种可能的解决方案是使用 JSON 序列化程序以字符串格式存储此属性的值,并在获取它时在应用程序中对其进行反序列化。
我找到了一个"简单"的解决方案来使用string
而不是Theme
作为Theme
属性的类型......
但是我想知道是否有一些方法可以自定义控制从表到对象的序列化/加载......
Azure 表存储客户端 SDK v8.0.0.0 引入了对使用 TableEntity 类上的 2 种新方法写入和读取具有复杂属性的复杂对象的支持。
要插入复杂对象,请通过TableEntity.Flatten
方法将其展平: https://learn.microsoft.com/en-us/dotnet/api/microsoft.windowsazure.storage.table.tableentity.flatten?view=azurestorage-8.1.3
并将平展的对象作为DynamicTableEntity
插入 Azure 表存储。
一旦你读回来,你就使用TableEntity.ConvertBack<TypeOfYourComplexObject
>
https://learn.microsoft.com/en-us/dotnet/api/microsoft.windowsazure.storage.table.tableentity.convertback?view=azurestorage-8.1.3#Microsoft_WindowsAzure_Storage_Table_TableEntity_ConvertBack__1_System_Collections_Generic_IDictionary_System_String_Microsoft_WindowsAzure_Storage_Table_EntityProperty__Microsoft_WindowsAzure_Storage_OperationContext_
将展平实体转换为其原始复数形式。 除了集合和 IEnumerable 类型外,还支持所有其他类型的属性复杂、简单、类、结构、枚举等。
Flatten 方法会将整个 Record 对象展平为平面结构,因此在您的示例中,记录对象上的复杂 Theme 属性将扁平化为 2 个键值对,具有相应的名称Theme_Description和 Theme_Key。其值将是在其字符串值创建的实体属性。因此,将记录对象写入表存储后,您可以单独访问(读取、投影、更新(此记录实体上的Theme_Description或Theme_Key属性。
还可以查看我撰写的有关将复杂的多层次结构对象写入 Azure 表存储的文章:https://doguarslan.wordpress.com/2016/02/03/writing-complex-objects-to-azure-table-storage/
除此之外,如果您想要自定义转换逻辑,即从字符串键属性到完整的主题属性,我建议您查看Retrieve
方法的重载版本,您可以在其中指定自定义 EntityProperty 转换器。 https://learn.microsoft.com/en-us/dotnet/api/microsoft.windowsazure.storage.table.tableoperation.retrieve?view=azurestorage-8.1.3#Microsoft_WindowsAzure_Storage_Table_TableOperation_Retrieve__1_System_String_System_String_Microsoft_WindowsAzure_Storage_Table_EntityResolver___0__System_Collections_Generic_List_System_String__